Binoy Babu
Binoy Babu

Reputation: 17119

Runtime.exec not working

I'm trying to run the following code to swap filenames. I'm using Runtime.exec. The code throws IOException. Anyway to fix this?

try {
Runtime.getRuntime().exec("file1=" + folderpath + " && file2=/mnt/sdcard/fsimages && temp=\"$(/system/xbin/mktemp -dp /mnt/sdcard)\" && /system/xbin/mv \"$file1\" $temp && /system/xbin/mv \"$file2\" \"$file1\" && /system/xbin/mv $temp/\"$file1\" \"$file2\"");
} catch (IOException e) {
    e.printStackTrace();
    return;
}

And the error:

02-28 07:48:02.936: W/System.err(14399): java.io.IOException: Error running exec(). Command: [file1=/mnt/sdcard/fsimages_3, &&, file2=/mnt/sdcard/fsimages, &&, temp="$(/system/xbin/mktemp, -dp, /mnt/sdcard)", &&, /system/xbin/mv, "$file1", $temp, &&, /system/xbin/mv, "$file2", "$file1", &&, /system/xbin/mv, $temp/"$file1", "$file2"] Working Directory: null Environment: null

It looks like Runtime.exec is inserting a coma before and after every &&. Seems like the issue is in the way which Runtime.exec interprets &&. Why is this happening? How can I prevent this?

Upvotes: 4

Views: 13389

Answers (2)

Stephen C
Stephen C

Reputation: 718886

If you use the Runtime.exec(String) overload, the string is treated as a command and its arguments, and is crudely split into substrings at white-space boundaries. This splitting is standard behaviour for that overload. (Refer to the javadoc.)

Runtime.exec(...) expects a native command and its arguments. You've provided a line of shell input. The exec methods don't understand shell input and don't know how to execute it properly. And the crude splitting (see above) messes up everything.

If you need to do that, then use the following:

String yourShellInput = "echo hi && echo ho";  // or whatever ... 
String[] commandAndArgs = new String[]{ "/bin/sh", "-c", yourShellInput };
Runtime.getRuntime().exec(commandAndArgs);

This is equivalent to running:

$ /bin/sh -c "echo hi && echo ho".

If sh is not installed as /bin/sh use the path where it is installed instead.

Upvotes: 14

Shahbaz Ali
Shahbaz Ali

Reputation: 1410

First of all the problem is not what you think "It looks like Runtime.exec is inserting a comma before and after every &&" actually the error statement is reporting your command that you gave in Runtime.exec() as String array (String[]). This is a standard behaviour of Java Runtime.exec() method.

02-28 07:48:02.936: 
W/System.err(14399): java.io.IOException: 
Error runningexec(). Command: 
[file1=/mnt/sdcard/fsimages_3, &&, file2=/mnt/sdcard/fsimages, &&, temp="$(/system/xbin/mktemp, -dp, /mnt/sdcard)", &&, /system/xbin/mv, "$file1", $temp, &&, /system/xbin/mv, "$file2", "$file1", &&, /system/xbin/mv, $temp/"$file1", "$file2"] 
Working Directory: null Environment: null

You can see in the error how Java interprets your command which you hardcoded, the String array you are getting back shows you that "file1=/mnt/sdcard/fsimages_3" is treated as opening command to execute and the rest " &&" , "file2=/mnt/sdcard/fsimages" etc. is treated as arguments.

What I think you should do is first try to split your command in an array like structure. as an example below

Process process;
String[] commandAndArgs = new String[]{ "/bin/sh", "mv", "/mnt/sdcard/fsimages_3","/mnt/sdcard/fsimages" };
process = Runtime.getRuntime().exec(commandAndArgs);

Next, your error shows that your working directory is null and your Environment is also null. So you need to set both of them for your process. From Java docs you can see it states this exec() overloaded method

exec(String[] cmdarray, String[] envp, File dir)

Executes the specified command and arguments in a separate process with the specified environment and working directory.

In case nothing stated works, I request you to kindly write a shell script file for your command and then set it executable using

chmod 755 or chmod +x script.sh;

then try to run that. I hope it works as in my case the script file approach worked.

Upvotes: 4

Related Questions