Perl script runs in terminal but doesn't run when invoked from Java program

java, perl, runtime.exec

Solution

`exec` uses `StringTokenizer` to parse the command, which apparently just splits on whitespace.

Take for example the following shell command (similar but different than yours):

perl -pi.back -e 's/a/b/g; s/c/d/g;' path/to/file1.txt

For it, `StringTokenizer` produces the following command and arguments:

- `perl` (command)

- `-pi.back`

- `-e`

- `'s/a/b/g;`

- `s/c/d/g;'`

- `path/to/file1.txt`

That's completely wrong. The command and arguments should be

- `perl` (command)

- `-pi.back`

- `-e`

- `s/a/b/g; s/c/d/g;` (Note the lack of quotes.)

- `path/to/file1.txt`

You could pass those above to `exec(String[] cmdarray)`. Or if you don't have the option of parsing the command, you could actually invoke a shell to parse it for you by passing the following to `exec(String[] cmdarray)`:

- `sh` (command)

- `-c`

- `perl -pi.back -e 's/a/b/g; s/c/d/g;' path/to/file1.txt`

Problem

I was running a Perl script that replaces a string with another: ``` perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt ``` When I run this command from terminal it well replaces all the occurrences of `str1` in the given file to `str2`. When I run this from java it does access the file but no replacement occurs: ``` Runtime.getRuntime().exec("perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt"); ``` - I'm sure it accesses the file (the file seems to be edited in gedit(reload required)). - I tried Java `ProcessBuilder` class but the same result happens. - When I use `Runtime.exec()` or `ProcessBuilder` with other commands (like `gedit newFile.txt`) they work well. - Ironically, I printed the above perl command from java and take the paste in terminal and the replace operation is done! - No exceptions or errors by using those commands. (I used try and catch to ensure this). - I also used `/usr/bin/perl` instead of `perl` in the cmd to ensure the perl cmd is executed. So what do you think the problem is? EDIT: I solved this problem by just removing the quotes from the command in java. Thanks to @ikegami for help. So the working version is: ``` perl -pi.back -e s/str1/str2/g; path/to/file1.txt ``` instead of ``` perl -pi.back -e 's/str1/str2/g;' path/to/file1.txt ```

Original source