2010-09-16 13:40:08 +0000 2010-09-16 13:40:08 +0000
88
88

如何用管道将命令输出到其他命令?

例如:

ls | echo什么也不打印(实际上是空行)。我希望它能打印一个文件列表。

ls | grep 'foo',另一方面,它的工作与预期的一样(打印名称中带有'foo'的文件)。

在这些情况下,我所做的是这样的事情。ls | while read OUT; do echo $OUT; done 但这很麻烦。

为什么管道对某些命令有效,而对其他命令无效?我怎样才能规避这个问题呢?

答案 (4)

123
123
123
2010-09-16 14:16:59 +0000

命令行参数和标准输入之间是有区别的。管道将一个进程的标准输出连接到另一个进程的标准输入。所以

ls | echo

将 ls 的标准输出连接到 echo 的标准输入。很好,对吧?好吧,echo会忽略标准输入,并将其命令行参数–在本例中没有参数–转储到自己的stdout。输出:什么都没有。

在这种情况下,有几种解决方案。一种是使用读取 stdin 并转储到 stdout 的命令,比如 cat。

ls | cat

会 “工作",这取决于你对工作的定义。

但一般情况下呢。你真正想要的是将一个命令的 stdout 转换为另一个命令行的 args。正如其他人所说,xargs是这种情况下的典范帮助工具,从它的stdin中读取它的命令行args,并构造命令来运行。

ls | xargs echo

你也可以将其转换一些,使用替换命令$()

echo $(ls)

也会达到你想要的目的。

这两个工具都是shell脚本的相当核心的工具,你应该学习这两个工具。

为了完整,正如你在问题中指出的,另一种将stdin转换为命令行args的基础方法是shell内置的read命令。它将 "单词"(IFS变量定义的单词)转换为一个临时变量,你可以在任何命令运行中使用它。

19
19
19
2010-09-16 13:54:37 +0000

ls | echo打印的只是空行,因为echo没有读取任何输入,管道的最后一条命令其实是echo,打印的只是空行。

一般情况下。

a | b

确保a的输出成为b的输入。我建议你阅读Pipelinesman bash部分。


如果你真的想把lsecho一起使用,这里有一些(很没用的)例子。

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
13
13
13
2010-09-16 14:03:04 +0000

如果你想用echo命令尝试。

ls | xargs echo

这将调用ls,输出为echo

3
3
3
2011-11-09 09:48:27 +0000

为什么不简单地使用:"

echo `ls`

或者更安全的是:

echo "`ls -lrt`"

或者更安全:

0x1&