Process。= Runtime.getRuntime()。exec()不适合我

时间:2013-03-28 14:54:48

标签: java linux inputstream runtime.exec

当我从java执行linux命令时它无法正常工作可以帮助我解决这个问题。

process3 = Runtime.getRuntime().exec(new String[] {"ls",
                    "-1s", 
                     "--block-size=1",
                      TStamp+"/received/i*.*",
                      "$dir|",
                      "awk",
"'{print $2\"\\t\"$1}'",
                           ">>",
                  "./"+TStamp+"/qa/manifest_QAG.txt"});
InputStream in1 = process3.getInputStream();              
BufferedReader br1=new BufferedReader(new InputStreamReader(in1));
String line1 =null;
while((line1=br1.readLine())!=null)
{
System.out.println(line1);
} 

Edit1:我试图列出文件并在manifest_QAG.txt中生成清单

实际命令在linux中有效:

ls -1s --block-size=1 20130328094916142/received/is*.* $dir| awk '{print $2"\t"$1}'

Edit2:我没有得到任何异常,甚至没有创建文件manifest_QAG.txt

编辑3:

3 个答案:

答案 0 :(得分:2)

您没有得到异常,因为ls命令不是Java,并且不与异常通信,而是在STDERR和退出代码上发送错误消息。

实际上,您必须了解在输入命令时shell执行的操作以及命令的作用。因此像这样的shell命令行

ls -1s --block-size=1 20130328094916142/received/is*.* $dir| awk '{print $2"\t"$1}'

由shell以这种方式处理:

  • shell:将20130328094916142/received/is*.*扩展为文件名列表
  • shell:将$dir部分展开为文件名列表
  • shell:使用参数执行ls命令
    • ls
    • -1s
    • --block-size=1
    • 每个扩展的文件名作为单独的参数
  • shell:使用参数执行awk命令
    • {print ...}
  • shell:将ls的输出连接到awk
  • 的输入
  • ls:评估参数
  • awk:读取每一行,用给定的脚本处理它并输出结果。

您会看到:环境变量和通配符的扩展由shell完成,而不是ls

回到Java: execute NOT 像shell一样处理参数。那取决于你。因此,您的调用大致相当于shell:

ls '-1s' '--block-size=1' '20130328094916142/received/is*.*' '$dir' '|' 'awk' '{print $2"\t"$1}'

所有内容都被引用,甚至是管道,因此shell不会扩展任何东西。

到目前为止的问题。有什么解决方案?

  • 您可以模拟shell并在Java中进行扩展。玩得开心。 (即,这不是一个真正的解决方案)。
  • 您可以使用Java而不是ls来调用shell。

后者是这样的:

一个shell通常有一个-c选项,你可以在其中给它一个命令字符串,然后以与真实类型命令行相同的方式对其进行评估。

所以你按照这个命令调用

String[] args = {
    "/bin/sh",
    "-c",
    "ls -1s --block-size=1 20130328094916142/received/is*.* $dir| awk '{print $2\"\t\"$1}'"
};
Process process3 = Runtime.getRuntime().exec(args);

虽然正确引用awk命令可能需要更多工作。

答案 1 :(得分:0)

我认为这里有一些错字

/received/i*.* is different from one that is in linux command /received/is*.*

希望有所帮助

答案 2 :(得分:0)

管道(|)不是ls的参数,而是shell的功能。如果你想使用Runtime #exec这样的管道,你必须启动一个shell,并将你希望shell解析和执行的命令字符串作为参数传递。

除非我遗漏了某些内容,否则列出目录并使用Java代码编写清单可能会更容易,而不是为简单的文件和字符串操作调用外部工具。