views:

357

answers:

2

I'm having difficulty executing a batch file in Java that expects parameters. These parameters may contain spaces so I need to wrap them in quotes. I will also need to do the same thing for Linux because some of the parameters may contain special characters such as !.

Non-functional Windows code:

ProcessBuilder pb = new ProcessBuilder(
        "cmd",
        "/c",
        "\"mybat.bat\"",
        "\"param 1\"",
        "\"param 2\"",
        "\"param 3\""
        );    

Non-functional Linux code:

ProcessBuilder pb = new ProcessBuilder(
        "bash",
        "-c",
        "'myshellscript.sh'",
        "'param 1'",
        "'param 2'",
        "'param 3'"
        ); 

I understand that I should be adding the parameters like the Windows example below, but this won't work with the spaces:

ProcessBuilder pb = new ProcessBuilder(
        "cmd",
        "/c",
        "mybat.bat param 1 param 2 param 3"
        );   

How should this be done?

+2  A: 

No, you should not quote the args on *nix. Quoting is necessary on *nix in an interactive shell to prevent the shell misinterpreting them, but when launching a process directly a shell isn't involved. Hence no need to quote.

If you do include the quotes, the launched process will see them as part of its incoming arguments and do things like (for example) try to open filenames containing quotes.

You also do not want the "-c" argument to bash. That tells it to parse the next argument as a command line, but you're supplying a list of arguments. Remove the "-c" option and the excess quotes and it should work.

The proper Linux call would be:

ProcessBuilder pb = new ProcessBuilder(
    "bash",
    "myshellscript.sh",
    "param 1",
    "param 2",
    "param 3"
    );

Also not that if the file "myshellscript.sh" is executable and has the appropriate shebang line (e.g. "#!/bin/bash"), you do not need the "bash" argument either. This is preferrable because if the script is ever replaced with one written in a different language you won't have to update your calling app.

Likewise, on Windows, you shouldn't need the "cmd" and "/c" arguments. The process launcher / OS should handle launching the batch file (based on extension) automatically.

Andrew Medico
Unfortunately I need the cmd and /c for windows. My shell script does have the shebang line, but I can't get it to work with or without sh.
hoffmandirt
+2  A: 

Windows:

ProcessBuilder pb = new ProcessBuilder(
        "cmd", "/c", "mybat.bat", 
        "param 1", "param 2", "param 3");

Unix:

ProcessBuilder pb = new ProcessBuilder(
        "sh", "mybat.sh", 
        "param 1", "param 2", "param 3");
Gladwin Burboz
I tried this, it works !!!
Gladwin Burboz
Why is this hapening? java.io.IOException: java.io.IOException: sh: not found at java.lang.UNIXProcess.<init>(UNIXProcess.java:148) at java.lang.ProcessImpl.start(ProcessImpl.java:65) at java.lang.ProcessBuilder.start(ProcessBuilder.java:451) at DmMdbConsumer.migrateData(DmMdbConsumer.java:328) at DmMdbConsumer.run(DmMdbConsumer.java:230) at java.lang.Thread.run(Thread.java:595)
hoffmandirt
"sh" had to be "/bin/sh" in my case. Thanks!
hoffmandirt
You may not be having an access to korn shell. Depending on which shell you have access to, use that shell (bash, csh, rsh) or you can make your script executable and remove "sh" paramater altogether.
Gladwin Burboz
"/bin" should have had been in your PATH. But if it's not and if you have execute permission on "/bin/sh", you can use that as well.
Gladwin Burboz
It appeared that nothing was on the path for linux. My first attempt at all of this was to execute java -jar instead of mybat.bat or myshell.sh. Windows worked fine, but no luck in Linux. I was able to open a terminal window in Linux and type java --version and get a version though.
hoffmandirt