The Runtime.exec(String ...) and Runtime.exec(String) methods allow you to execute a command as an external process1. In the first version, you supply the command name and the command arguments as separate elements of the string array, and the Java runtime requests the OS runtime system to start the external command. The second version is deceptively easy to use, but it has some pitfalls.

First of all, here is an example of using exec(String) being used safely:

Process p = Runtime.exec("mkdir /tmp/testDir");
p.waitFor();
if (p.exitValue() == 0) {
    System.out.println("created the directory");
}

Spaces in pathnames

Suppose that we generalize the example above so that we can create an arbitrary directory:

Process p = Runtime.exec("mkdir " + dirPath);
// ...

This will typically work, but it will fail if dirPath is (for example) “/home/user/My Documents”. The problem is that exec(String) splits the string into a command and arguments by simply looking for whitespace. The command string:

"mkdir /home/user/My Documents"

will be split into:

"mkdir", "/home/user/My", "Documents"

and this will cause the “mkdir” command to fail because it expects one argument, not two.

Faced with this, some programmers try to add quotes around the pathname. This doesn’t work either:

"mkdir \\"/home/user/My Documents\\""

will be split into:

"mkdir", "\\"/home/user/My", "Documents\\""

The extra double-quote characters that were added in attempt to “quote” the spaces are treated like any other non-whitespace characters. Indeed, anything we do quote or escape the spaces is going to fail.

The way to deal with this particular problems is to use the exec(String ...) overload.

Process p = Runtime.exec("mkdir", dirPath);
// ...

This will work if dirpath includes whitespace characters because this overload of exec does not attempt to split the arguments. The strings are passed through to the OS exec system call as-is.

Redirection, pipelines and other shell syntax