java - 使用 Java 获取终端多参数命令的输出
问题描述
我正在尝试从 shell 命令解析 java 中的输出:(可以从 apt 安装 sox)
sox inputfile.flac -n stat
但我不能,几个小时的搜索,一无所获。
代码:
Process p = Runtime.getRuntime().exec(command);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
我尝试使用命令:
String command1 = "sox inputfile.flac -n stat"; //no output
String command2 = "bash -c sox inputfile.flac -n stat"; //output of 'sox' without arguments
String command3 = "sh -c sox inputfile.flac -n stat"; //output of 'sox' without arguments
String command4 = "sh -c \"sox inputfile.flac -n stat\""; //error
String command5 = "bash -c \"sox inputfile.flac -n stat\""; //error
根据文档 od 'sh':
-c 选项导致从字符串操作数而不是标准输入中读取命令。请记住,此选项仅接受单个字符串作为其参数,因此必须引用多字字符串。
所以我尝试了“command4”/“command5”->错误代码2。但是,我检查了普通的linux终端并且它工作正常:
sh -c "sox inputfile.flac -n stat"
bash -c "sox inputfile.flac -n stat"
sox inputfile.flac -n stat
我错过了什么?
解决方案
您缺少的是 Process/Runtime 不是 bash。Bash 在实际运行之前对命令行执行操作。您不能在 ProcessBuilder 和朋友(Runtime.exec、Process 和 ProcessBuilder)中做这些事情。
变成*.txt
所有文件的列表?那是巴什。
转入hello foo bar "baz boz"
概念:应用程序被调用hello
,它得到 3 个参数,, foo
,bar
和baz boz
? 那是 bash。Bash 执行“哦,引号,那些需要捆绑起来”。
作为一般规则,不要使用单字符串版本。使用java.lang.ProcessBuilder
.
另请注意,翻译bash
为/bin/bash
也是一种bashism。
最后,请注意,根据平台和月相,Runtime.exec 和朋友会做一些 bashisms。也许。问题是,它不可靠,所以不要依赖它(例如,在 Windows 上,*.txt
通常可以工作,而在所有非 Windows 操作系统上它几乎永远不会,并且 Runtime.exec 确实做了一些应用程序$PATH
,但不一定以与 bash 相同的方式)。
// Always absolute-path your executables.
// Always pass args separately.
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "sox inputfile.flac -n stat");
Process p = pb.start();
请注意,第二个字符串(带有 的字符串sox...
)被传递给 bash。因此,如果您想在其中使用字符串转义符和星星,请随意。Bash 将处理它,而不是 ProcessBuilder:
// This won't work:
ProcessBuilder pb = new ProcessBuilder("ls", "*.txt");
// but this will:
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "ls *.txt");
*) 这是相当普遍的说法,但在我说“bashism”的地方,请随意插入您选择的外壳或“shellism”。关键是,它是一个外壳程序,它接收您在命令行上键入的内容并在将其实际传递给操作系统之前对其进行处理。Runtime.exec 和 co 也需要做这个处理;它的处理更加有限,您应该尽可能避免它:绝对路径,并单独列出 args。
推荐阅读
- node.js - 找不到模块“../encodings”
- javascript - 从 JSON 对象角度 10 将值设置为嵌套表单组
- java - java - 如何使用基于此身份的递归计算Java中的幂
- ios - -[NSConcreteNotification count]:无法识别的选择器发送到实例 0x2816dd380
- python - 即使在安装包后在 Conda 环境中获取 ModuleNotFoundError
- powershell - PowerShell 嵌套 ForEach 循环的问题
- json - 在 VueJS 中从 JSON 水平制作表格
- javascript - 登录后在哪里以及如何更改会话用户对象?
- sql - SQL Server - 获取具有值的逗号分隔的列名
- javascript - 单击标签应关闭不起作用的选项卡