Reputation: 359
Is it possible to pass the output of one process created by ProcessBuilder to another process created by another ProcessBuilder? For example, if I'm trying to execute this shell command:
ls | grep build.xml
how should I do it with ProcessBuilder?
as @erdinc suggested, I tried this:
Process process = Runtime.getRuntime().exec("ls");
InputStream is = process.getInputStream();
byte[] buf = new byte[1000];
is.read(buf);
String parameter = new String(buf);
System.out.println("grep build " + parameter);
Process proc2 = Runtime.getRuntime().exec("grep build " + parameter);
InputStream is2 = proc2.getInputStream();
byte[] buf2 = new byte[1000];
is2.read(buf2);
String result = new String(buf2);
System.out.println("proc2 result: " + result);
but it produces different result compare to when I run the script directly in the shell. Where did I do wrong?
Solved: Please see Philipp Wendler solution
Upvotes: 10
Views: 4160
Reputation: 11433
The problem with the solution you have is that it reads only the first 1000 bytes from the output of ls and passes them to grep. As you don't know the amount of output from ls before, you need to read it iteratively until it is exhausted.
Here is a solution using BufferedReader, which will send each line of output to grep:
Process lsProcess = Runtime.getRuntime().exec("ls");
BufferedReader lsOutput = new BufferedReader(new InputStreamReader(lsProcess.getInputStream()));
Process grepProcess = Runtime.getRuntime().exec("grep build.xml");
BufferedWriter grepInput = new BufferedWriter(new OutputStreamWriter(grepProcess.getOutputStream()));
String line;
// read each line from ls until there are no more
while ((line = lsOutput.readLine()) != null) {
// and send them to grep
grepInput.write(line);
grepInput.newLine();
}
// send end-of-file signal to grep so it will terminate itself
grepInput.close();
Of course you need to add the appropriate error-handling here.
You can omit the Reader and Writer and pass byte[]
arrays directly from the input to the output stream if this solution is too slow.
However, a much better solution would be not to use ls and grep to look for a file in the filesystem, but to use the appropriate Java API. For example if you create a File
object for the directory you are interested in, you can use the various listFiles
methods on it to list all files in this directory. This method is much easier, portable, less error-prone and probably faster.
Upvotes: 6
Reputation: 1578
You can use getInputStream method than pass as parameter second Process. Example code;
process = Runtime.getRuntime().exec("ls");
InputStream is = process.getInputStream();
byte[] buf = new byte[1000];
is.read(buf);
String parameter = new String(buf);
System.out.println(parameter);
Runtime.getRuntime().exec("grep build.xml " + parameter);
Upvotes: 0