Reputation: 2563
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?
Upvotes: 0
Views: 393
Reputation: 262824
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".
Upvotes: 2
Reputation: 40078
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).
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).
cmdarray - array containing the command to call and its arguments.
Upvotes: 1