问题描述
我正在尝试从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 Terminal及其运行情况:
sh -c "sox inputfile.flac -n stat"
bash -c "sox inputfile.flac -n stat"
sox inputfile.flac -n stat
我想念什么?
解决方法
您缺少的是流程/运行时不是猛烈的打击。 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","ls *.txt");
*)这是相当普遍的说法,但是在我说“ bashism”时,请随意插入您选择的shell或“ shellism”。关键是,它是一个外壳,可以将您在命令行上键入的内容进行处理,然后再将其实际传递给操作系统。 Runtime.exec和co也需要执行此处理;它的处理FAR受更多限制,因此您应尽可能避免:绝对路径,并分别列出args。