如何将命令输出通过管道传输到其他命令?

Mih*_*aru 107 bash pipe

例子:

ls | echo不打印任何内容(实际上是一个空行)。我希望它打印文件列表。

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

我在这些情况下所做的类似于: ls | while read OUT; do echo $OUT; done但这相当麻烦。

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

Ric*_*lka 151

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

ls | echo
Run Code Online (Sandbox Code Playgroud)

将 ls 的标准输出连接到 echo 的标准输入。好吗?好吧,echo 会忽略标准输入并将其命令行参数(在这种情况下没有)转储到它自己的标准输出。输出:什么都没有。

在这种情况下有几种解决方案。一种是使用读取标准输入并转储到标准输出的命令,例如 cat。

ls | cat
Run Code Online (Sandbox Code Playgroud)

会“工作”,这取决于您对工作的定义。

但是一般情况呢。您真正想要的是将一个命令的 stdout 转换为另一个命令的命令行参数。正如其他人所说,xargs在这种情况下是规范的帮助器工具,从其标准输入读取命令的命令行参数,并构建要运行的命令。

ls | xargs echo
Run Code Online (Sandbox Code Playgroud)

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

echo $(ls)
Run Code Online (Sandbox Code Playgroud)

也会做你想做的。

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

为了完整起见,正如您在问题中所指出的,将 stdin 转换为命令行 args 的另一种基本方法是 shell 的内置read命令。它将“词”(由IFS变量定义的词)转换为临时变量,您可以在任何命令运行中使用该变量。

  • 一个非常有用的信息丰富的答案,谢谢!我目前正在学习 bash,我之前见过 xargs 和 $(*) 符号,但并没有太注意它们。现在我知道它们有多重要,并且肯定会研究它们。 (2认同)
  • xargs 可能正是 OP 正在寻找的东西。 (2认同)

cYr*_*rus 20

ls | echo只打印一个空行,因为echo没有读取输入;管道的最后一个命令实际上echo只打印一个空行。

一般来说:

a | b
Run Code Online (Sandbox Code Playgroud)

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


如果你真的想使用lsecho聚集在这里的一些(相当无用的)例子:

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
Run Code Online (Sandbox Code Playgroud)


Nat*_*man 15

如果你想echols命令试试:

ls | xargs echo
Run Code Online (Sandbox Code Playgroud)

这将调用echo与输出ls

  • 或者`ls | xargs -I {} echo {}` 如果您希望为每一行单独调用它 (4认同)