我不太明白管道在 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