ProcessBuilder and quotes

Recently, I have spent few happy hours chasing a bug in my code. It was connected to the ProcessBuilder class. This class was introduced to Java 5 in order to simplify calling of external processes.

I needed to run following rsync command, to synchronize some files from the server. It simply takes all *.txt files from all directories and ignores all other files.


rsync -vtlr --include="*.txt" --include="**/" --exclude="*" rsync.example.org::module ./mirror

With ProcessBuilder it is easy, you just have to write the following code.



    ProcessBuilder pb = new ProcessBuilder("rsync","-vtlr""--include=\"*.txt\"","--include=\"**/\"""--exclude=\"*\"""rsync.example.org::module""./mirror");
    pb.directory(directory);
    Process process = pb.start();
    int result = process.waitFor();

It works good, without any problem. But only on Windows. When I deployed the application on the Linux server, it synchronized all the files. It looked like that --exclude directive was simply ignored.

The weird thing was, that when I run the command from the shell it worked as it was supposed to run. The usual suspects were the quotes. Since the command worked, only some parameters were ignored, it was evident that the problem is subtle. I tried to replace double quotes with single quotes, put all parameters to one. I even tried to call the command using Runtime.exec(). It was just vain effort. (Runtime.exec() internally uses ProcessBuilder). The solution is simple. Just remove all the quotes from all parameters.



ProcessBuilder pb = new ProcessBuilder("rsync","-vtlr""--include=*.txt","--include=**/""--exclude=*""rsync.example.org::module""./mirror");
    pb.directory(directory);
    Process process = pb.start();
    int result = process.waitFor();

Like this, it works on both Linux and Windows.

5 Responses to “ProcessBuilder and quotes”

  1. Seth Tisue Says:

    The purpose of the quotes was to prevent characters like * from being interpreted specially by the shell. Only the shell sees the quotes; the shell strips them out before passing the arguments to the rsync command.

    But ProcessBuilder doesn't use a shell; it runs the command directly. Since there's no shell involved, the quotes aren't needed, and if you include them, they will not be stripped out, causing the rsync command to become confused about your intentions.

    Why it would have worked on Windows with the quotes, I don't know.

  2. lanes Says:

    man, this is the page i looking for.
    this is exactly the same problem with me.
    thanks dude.

  3. same problem here Says:

    any solution? i have the same problem...

  4. david van brink Says:

    Quoting and execs. I'm debugging some java code where the author has worked around anticipated downstream quoting bugs... the thing it's launching happens to be a csh script that in fact loses some quotes, spaces... the usual.

    Thanks for mentioning that quotes-not-needed on windows, works great. thankyou thankyou!

  5. Marcel Says:

    Had the same problem with running solr from a junit test, removing to quotes fixed the problem 🙂