使用Java ProcessBuilder执行管道命令

use*_*889 32 java command-line

我正在尝试使用Java的ProcessBuilderClass来执行一个包含管道的命令.例如:

ls -l | grep foo
Run Code Online (Sandbox Code Playgroud)

但是,我收到一个错误:

ls: |: no such file or directory
Run Code Online (Sandbox Code Playgroud)

其次是:

ls: grep: no such file or directory
Run Code Online (Sandbox Code Playgroud)

即使该命令在命令行中运行良好,我也无法ProcessBuilder执行将其输出重定向到另一个命令的命令.有没有办法实现这个目标?

dog*_*ane 60

这应该工作:

ProcessBuilder b = new ProcessBuilder("/bin/sh", "-c", "ls -l| grep foo");
Run Code Online (Sandbox Code Playgroud)

要执行管道,您必须调用shell,然后在该shell中运行命令.

  • 扩展通配符的是 shell,而不是 ls。如果你输入 `ls '/dev/sd*'` 那么这也不起作用。 (2认同)

Jon*_*eet 5

最简单的方法是使用命令行作为参数调用shell.毕竟,它是解释"|"的shell 表示"在两个进程之间管道数据".

或者,您可以单独启动每个进程,并从"ls -l"的标准输出中读取,将数据写入示例中"grep"的标准输入.


Hol*_*ger 5

从 Java\xc2\xa09 开始,\xe2\x80\x99sProcessBuilder.

\n

所以你可以使用

\n
List<String> result;\nList<Process> processes = ProcessBuilder.startPipeline(List.of(\n        new ProcessBuilder("ls", "-l")\n            .inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE),\n        new ProcessBuilder("grep", "foo")\n            .redirectError(ProcessBuilder.Redirect.INHERIT)\n    ));\ntry(Scanner s = new Scanner(processes.get(processes.size() - 1).getInputStream())) {\n    result = s.useDelimiter("\\\\R").tokens().toList();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

获取列表中的匹配行。

\n

或者,对于 Windows

\n
List<String> result;\nList<Process> processes = ProcessBuilder.startPipeline(List.of(\n        new ProcessBuilder("cmd", "/c", "dir")\n            .inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE),\n        new ProcessBuilder("find", "\\"foo\\"")\n            .redirectError(ProcessBuilder.Redirect.INHERIT)\n    ));\ntry(Scanner s = new Scanner(processes.get(processes.size() - 1).getInputStream())) {\n    result = s.useDelimiter("\\\\R").tokens().toList();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这些示例将第一个进程的stdin和所有错误流重定向到继承,以与 Java 进程相同的方式使用。

\n

您还可以调用.redirectOutput(ProcessBuilder.Redirect.INHERIT)最后ProcessBuilder一个进程的 ,将结果直接打印到控制台(或stdout已重定向到的任何地方)。

\n