例子:
ls | echo
什么都不打印(实际上是一个空白行)。我期望它打印文件列表。
ls | grep 'foo'
另一方面,按预期工作(打印名称中带有“foo”的文件)。
在这种情况下,我会这样做:
ls | while read OUT; do echo $OUT; done
但这相当麻烦。
为什么管道对某些命令有效,而对其他命令无效?我该如何解决这个问题?
答案1
命令行参数和标准输入之间存在区别。管道将一个进程的标准输出连接到另一个进程的标准输入。因此
ls | echo
将 ls 的标准输出连接到 echo 的标准输入。很好吧?嗯,echo 会忽略标准输入,并将其命令行参数(在本例中为无)转储到其自己的标准输出。输出:什么都没有。
这种情况有几种解决方案。一种是使用读取 stdin 并转储到 stdout 的命令,例如 cat。
ls | cat
将会“工作”,这取决于您对工作的定义。
但是一般情况呢?您真正想要的是将一个命令的标准输出转换为另一个命令的命令行参数。正如其他人所说,xargs
在这种情况下,规范的辅助工具是从命令的标准输入读取命令的命令行参数并构造要运行的命令。
ls | xargs echo
您也可以使用替换命令$()
来执行您想要的操作。
echo $(ls)
这两个工具都是 Shell 脚本的核心,您应该学习它们。
为了完整起见,正如您在问题中指出的那样,将 stdin 转换为命令行参数的另一种基本方法是使用 shell 的内置read
命令。它将“单词”(由变量定义的单词IFS
)转换为临时变量,您可以在任何命令运行中使用该变量。
答案2
ls | echo
由于没有读取输入,因此仅打印一个空白行echo
;管道的最后一个命令实际上echo
只打印一个空白行。
一般来说:
a | b
确保的输出a
成为的输入b
。我建议你阅读Pipelines
的部分man bash
。
如果您确实想一起使用ls
,echo
这里有一些(相当无用的)示例:
ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
答案3
如果您想要echo
该ls
命令尝试:
ls | xargs echo
这将调用echo
的输出ls
。