了解 Bash 中输入如何发送到管道

了解 Bash 中输入如何发送到管道

我不太明白管道在 bash 中是如何工作的。

我知道它将一个命令的输出作为另一个命令的输入。

我可以获得输出是什么,因为它是命令打印到屏幕上的内容。

但是我怎么知道命令需要什么输入?

这是一个我认为可行的例子:

which gem | rm

不幸的是,事实并非如此。

哪个宝石打印出来/usr/bin/gem一定是输出正确的?

我以为那是给了 rm 所以会是这样的rm /usr/bin/gem但我错了。

所以我的问题是,我如何知道命令需要什么输入?

答案1

“输入”和“命令行参数”是不同的东西。

rm删除作为参数提供的文件。

管道将左侧命令的输出重定向到右侧命令的输入。它不会影响右侧程序的命令行参数。

要执行您要执行的操作,请尝试使用xargs将标准输入转换为用于执行程序的命令行参数。这就是它的工作。

which gem | xargs rm例如,将从gem你的 PATH 中删除。

答案2

rm不接受输入,它接受参数。它们是不同的。参数是您在命令行上提供给程序以影响其行为的开关和文件名等。输入是程序处理的数据。例如,grep接受输入和参数:

grep "foo" file.txt

这里有两个参数:"foo"file.txt输入是个内容file.txt不是字符串file.txt本身。由于 grep 接受输入,因此您可以将它与管道一起使用:

cat file.txt | grep "foo"

产生相同的输出,因为 cat 接受file.txt一个参数,并产生内容作为file.txt输出。然后,该输出通过管道传输到 grep,其效果与让 grep 本身打开文件相同,如第一个示例中所示。

如果你想使用一个程序的输出作为争论另一方面,你使用反引号:

rm `which gem`

或者这个替代的(bash 特定的)语法:

rm $(which gem)

编辑:或者xargs正如另一位回答者指出的那样。使用命令行有很多方法可以解决问题。

答案3

查看man您感兴趣的命令页面。这些程序将表明它们从哪里读取stdin(尝试man grep读取 stdin 的流行命令)。

答案4

如果您的 PATH 中的目录包含空格或命令名称包含空格,运行这些命令都很危险:

rm `which gem`       # Dangerous
rm $(which gem)      # Dangerous
which gem | xargs rm # Dangerous

GNU 并行https://www.gnu.org/software/parallel/没有这个问题,所以即使你的 PATH 中的目录包含空格或者命令名称包含空格,这也会起作用:

which gem | parallel rm
parallel -a <(which bass) rm

观看 GNU Parallel 的介绍视频: http://www.youtube.com/watch?v=OpaiGYxkSuQ

相关内容