1

I have a function to execute a system command:

public String cmd(String s) {
    String out = "";
    try {
        Runtime run = Runtime.getRuntime();
        Process pr = run.exec(s.split(" "));
        pr.waitFor();
        BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        String line = "";
        while ((line=buf.readLine())!=null) {
            out+=line+"\n";
        }
    } catch(Exception e) {
        e.printStackTrace();
    }
    return out;
}

The command passes through:

cmd("nmap -sL -n 192.168.1.0/24 | awk '/Nmap scan report/{print $NF}'");

Expected Output:

192.168.1.0
192.168.1.1
 ...

Actual Output:

Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-12 20:27 EET
Nmap scan report for 192.168.1.0 ...
0

2 Answers 2

2

Similar questions answers this well:

To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.

Process p = new ProcessBuilder().command("bash", "-c", command).start();

bash invokes a shell to execute your command and -c means commands are read from string. So, you don't have to send the command as an array in ProcessBuilder.

Adapted to you case

String cmd(String command) {
  ProcessBuilder builder = new ProcessBuilder();
  builder.redirectErrorStream(true); // add stdErr to output

  Process process = builder.command("bash", "-c", command).start();
    
  StringBuilder processOutput = new StringBuilder(); // add lines easier
  // try-with to auto-close resources
  try (BufferedReader processOutputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));) {
    String readLine;
    while ((readLine = processOutputReader.readLine()) != null) {
      processOutput.append(readLine + System.lineSeparator()); // use system's line-break
    }

    process.waitFor();
  }

  return processOutput.toString().trim();
}

Then call as expected:

cmd("nmap -sL -n 192.168.1.0/24 | awk '/Nmap scan report/{print $NF}'");

Note: I enhanced it a bit to

Inspired by: read the output from java exec

Sign up to request clarification or add additional context in comments.

Comments

1

The pipe is interpreted by the shell. It executes one command then passes the output of one command into the next one. You could emulate this in Java starting both commands and then pumping the OutputStream of the first program to the InputStream of the second.

Alternatively if you don't want to do this you can still call something like "sh -c 'command1 | command2"

1 Comment

Could you please show an example of emulating the passing of the output of cmd1 to cmd2 ? Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.