Piping problem
I recently had a task wherein I was required to call few Perl routines from inside my Java class. You must be saying, what’s the big deal? Runtime.exec is what one needs. You are dead right, this comes to rescue when ones needs to call a non-Java process or an executable. With this, I was able to call most of the said routines, except a few that were using “Piping”.
Now, a pipe is a one-way I/O channel which can transfer a stream of bytes from one process to another, meaning that the standard output for one process serves as a pipe to another program; anything you print to STDOUT will be standard input for the other process.
With a piped routine call as follows, only routine1 got executed and routine2 didn’t.
[code lang=”java”]./routine1.pl param1 | ./routine2.pl -directory param2[/code]
Some search revealed that people were facing problems too and I had no clue as to how I could use the Standard output from the Process object to feed to second routine.
I finally found the solution here, like the light at the end of tunnel. As the article says, Runtime.exec invokes actual executable binary programs. Syntax such as pipe (|) and > are part of a particular command processor, and are only understood by that processor. So in such calls, the command preceding the pipe is executed, but the rest of the shell command is not. Moreover, invoking the process with single string argument, say as “sh -c ‘./routine1.pl param1 | ./routine2.pl -directory param2′” doesn’t work because the String passed to exec method is split apart into tokens without caring for the single inner quotes.
Without further ado, let me reveal that invoking the process as follows is what works:
[code lang=”java” highlight=”1″]
String param = "./routine1.pl param1 | ./routine2.pl -directory param2";
Runtime runtime = Runtime.getRuntime();
String[] args = new String[]{"sh", "-c", param};
Process p = runtime.exec(args);
[/code]
Nice blog you have here, dude.
I had a similar problem a couple of weeks ago but that only involved redirecting an “ls” to an input stream. Coincidentally (or not) I too found what I wanted on the same thread on jGuru that you’ve linked to.
cheers
-N