如何用管道将命令输出到其他命令?
例如:
ls | echo
什么也不打印(实际上是空行)。我希望它能打印一个文件列表。
ls | grep 'foo'
,另一方面,它的工作与预期的一样(打印名称中带有'foo'的文件)。
在这些情况下,我所做的是这样的事情。ls | while read OUT; do echo $OUT; done
但这很麻烦。
为什么管道对某些命令有效,而对其他命令无效?我怎样才能规避这个问题呢?
例如:
ls | echo
什么也不打印(实际上是空行)。我希望它能打印一个文件列表。
ls | grep 'foo'
,另一方面,它的工作与预期的一样(打印名称中带有'foo'的文件)。
在这些情况下,我所做的是这样的事情。ls | while read OUT; do echo $OUT; done
但这很麻烦。
为什么管道对某些命令有效,而对其他命令无效?我怎样才能规避这个问题呢?
命令行参数和标准输入之间是有区别的。管道将一个进程的标准输出连接到另一个进程的标准输入。所以
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
变量定义的单词)转换为一个临时变量,你可以在任何命令运行中使用它。
如果你想用echo
命令尝试。
ls | xargs echo
这将调用ls
,输出为echo
。