Reputation: 220
I am trying to run following command in my Java program
Runtime.getRuntime().exec("ls -lrt service/logs/post/level2.log | awk '{print $9}'");
or
Runtime.getRuntime().exec("ls -lrt service/logs/post/level2* | awk '{print $9}'");
it gives me following error
ls: 0653-341 The file | does not exist. ls: 0653-341 The file awk does not exist. ls: 0653-341 The file '{print does not exist. ls: 0653-341 The file $9}' does not exist.
Kindly help me
Upvotes: 1
Views: 2494
Reputation: 103847
Pipes are a shell-based construct, not actual runnable commands. There are two options to do this as I see it:
ls
command first, get a handle to its OutputStream
and then invoke awk
connecting the first Process
's output to the second Process
' input stream.-c
parameter. That way all the piping is done within the single process.As for the token-based errors, you should be invoking these commands with an array of strings; each element represents a token of the command line. So try, for example:
Runtime.getRuntime().exec(new String[] { "ls", "-lrt", "service/logs/post/level2.log" });
in order to invoke the ls command. I don't think this is strictly necessary in this case, but it will be for the awk
command, since Java doesn't know anything about shell-specific quoting rules, so by default tokenises a single-string input on the space character. That's why your awk script was being split in two.
Edit (in response to comments): In the first option, I meant simply that you're able to pipe the output between the two processes yourself, in Java.
Imagine if you've created a process as so:
Process ls = Runtime.getRuntime().exec("ls -lrt service/logs/post/level2.log");
Now, this process will run and generate some output (which we know is going to be a line describing that file). We can get the stream for this output like so:
InputStream lsOut = ls.getInputStream();
Now, we want to run that awk process:
Process awk = Runtime.getRuntime().exec(new String[] { "awk", "{print $9}"});
The awk process of course will sit there are the moment waiting for input, since it knows it's going to be reading from stdin. So, we grab the input stream that it's going to be using:
OutputStream awkIn = awk.getOutputStream();
Now, the piping bit - we read the output of the ls command and pass it into the input for awk:
// TODO add buffering, error handling, probably run this in a separate thread
int datum = lsOut.read();
while (datum != -1)
{
awkIn.write(datum);
datum = lsOut.read();
}
This reads the output of ls
(byte-by-byte for simplicity, using byte array buffers would be much faster but I'm trying to illustrate the concept simply) and writes it to the input of awk
.
Then it's just a matter of reading the output from the awk
process and dealing with it as you see fit.
Upvotes: 9