0

I try to call a vim editor with a file on a specific position from within a java process:

Runtime.getRuntime().exec("gvim /etc/fstab '+normal GW'");

Unfortunately that doesn't work. It gives a strange error message from gvim which doesn't help finding the problem ("/etc/fstab" "/etc/fstab" [readonly] 12L, 664C).

The same command directly entered into a terminal works well.

I tried to modify the command:

Runtime.getRuntime().exec("gvim /etc/fstab +normal\ GW");

which also works when entered directly in a terminal. But this gives the exact same behaviour.

What does work ist splitting the command and its parameters into a String[]:

Runtime.getRuntime().exec(new String[]{"gvim", "/etc/fstab" ,"+normal GW"});

What is the reason for this behaviour? How can I call the above mentioned command as a single string from within Java?

4
  • Use ProcessBuilder. ProcessBuilder pb = new ProcessBuilder("gvim","/etc/fstab","'+normal\ GW'"); pb.start(); Commented Jul 12, 2019 at 7:35
  • @PrasanthGanesan that is not a single string either. Commented Jul 12, 2019 at 7:35
  • Then this could work Commented Jul 12, 2019 at 7:37
  • @PrasanthGanesan No that shows exactly the same behaviour. Commented Jul 12, 2019 at 9:01

2 Answers 2

2

exec is not a complete shell.

As a convenience, it does allow you to pass a single String with both executable name and parameters (as opposed to using the String[] version), but the logic that it uses to split that String is very simple, it just calls new StringTokenizer(command), which just splits by whitespace and has no understanding of special quoting and escaping behaviour a full command shell would offer.

So your single quotes are not being respected.

gvim /etc/fstab '+normal GW'   // last quoted section supposed to be a single arg

becomes

String[]{ "gvim", "/etc/fstab", "'+normal", "GW'" } // four args instead of three

How can I call the above mentioned command as a single string from within Java?

Do you really need this? Unless the application dynamically accepts command line input from an interactive user, it should be possible to split the arguments when you write the program. Much safer that way.

If you really need this, you could pass your whole string to a command shell.

Try Runtime.getRuntime().exec(new String[]{"bash", "-c", theCommand });

But there is some overhead involved.

Other than that, you could try to find a Java library that can split the string "properly".

Sign up to request clarification or add additional context in comments.

3 Comments

Note that unlike StringTokenizer, the Stackoverflow syntax highlighter does understand the quotes in the first code block and colours the parameter properly.
Unless the application dynamically accepts command line input from an interactive user. Unfortunately this is the case. My example was only one possible example. Since it should even work under Windows, I would not like to call a specific shell (like bash). Have to think a bit about that. But thanks for your explanation. That the string is tokenized in such a simple way is the actual problem. Maybe doing that myself could be a solution.
1

According to documentation exec(String command) is treating whole string as a command, if we look at the documentation

public Process exec(String command)
         throws IOException

Executes the specified string command in a separate process.

This is a convenience method. An invocation of the form exec(command) behaves in exactly the same way as the invocation exec(command, null, null).

Parameters:

command - a specified system command.

And coming to exec(String[] cmdarray) it will treat cmdarray as array containing the command to call and its arguments.This is the only difference between these two methods which might be the issue

public Process exec(String[] cmdarray)
         throws IOException

Executes the specified command and arguments in a separate process.

This is a convenience method. An invocation of the form exec(cmdarray) behaves in exactly the same way as the invocation exec(cmdarray, null, null).

Parameters:

cmdarray - array containing the command to call and its arguments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.