Linux为什么我不能管道找到rm的结果?

时间:2013-12-01 00:24:47

标签: linux bash find pipe rm

抱歉,如果这是一个noobie问题,但我找不到一个好的答案。

要查找然后删除我可以使用的内容

find . -name ".txt" -exec rm "{}" \;

但为什么我不能把结果传递给rm像

find . -name ".txt" | rm 
像我将它传递给grep一样

find . -name ".txt" | grep a

我从某个地方读过rm不接受来自stdin的输入,因此我无法管道但是这意味着什么?当我输入rm a.txt时,它会从标准输入中读取,就像我可以直接读取一样吗?或者stdin和命令行之间有区别。救命啊!

4 个答案:

答案 0 :(得分:85)

扩展@Alex Gitelman的答案:是的,“标准输入”与命令行之间存在差异。

当您键入rm a.txt b.txt c.txt时,您在rm之后列出的文件称为参数,并通过特殊变量(称为argv)提供给rm内部)。另一方面,标准输入查看Unix程序,如名为stdin的文件。程序可以从这个“文件”中读取数据,就像在磁盘上打开常规文件并从中读取数据一样。

与许多其他程序一样,

rm从命令行获取其参数但忽略标准输入。你可以把任何东西送到你喜欢的地方;它只会抛弃那些数据。这就是xargs派上用场的地方。它读取标准输入上的行并将它们转换为命令行参数,因此您可以有效地将数据传输到另一个程序的命令行。这是一个巧妙的技巧。

例如:

find . -name ".txt" | xargs rm
find . -name ".txt" | grep "foo" | xargs rm  

请注意,如果有任何包含换行符或空格的文件名,则无法正常工作。 要处理包含换行符或空格的文件名,您应该使用:

find . -name ".txt" -print0 | xargs -0 rm

这将告诉find使用空字符而不是换行符终止结果。 但是,grep将无法像以前那样工作。而是使用它:

find . -name ".txt" | grep "foo" | tr "\n" "\0" | xargs -0 rm

此时tr用于将所有换行符转换为空字符。

答案 1 :(得分:5)

“为什么我不能将结果发送到rm?”

当您将某些内容传递给程序时,管道将替换键盘输入。记住这一点,并问自己下一个问题:rm键盘会做什么?删除你的击键? (确实有点傻)接受互动控制? (rm不是交互式的,除非有时需要确认,确实可以通过管道给出。)

事实上,当rm已经运行时,你无法输入命令让它删除文件....所以你不能用管道做到这一点。

如果您记住管道取代了键盘/屏幕组合,事情会立即变得更合乎逻辑。

现在反过来了。 您可以将数据流传输到grep。 这是否意味着您可以让grep读取键盘上的击键作为输入数据?

YES!这实际上就是它本身(没有管道)的作用。

(b.t.w。请注意,您无法将搜索参数输入管道或输入grep

所以现在你知道为什么你不能管道到rm 并且期望它作为命令行参数。

tl; dr:

根据UNIX哲学对程序进行剖析:
文件输入,文件输出,键盘输入,屏幕输出。 - > Pipe只会替换键盘和屏幕。

答案 2 :(得分:4)

Pipe将第一个命令的输出发送到第二个标准输入。 rm不接受标准输入,因此您无法管道输入。您可以使用xargs来达到相同的效果。 您可以在man page for xargs中专门针对您的案例找到xargs的示例。

答案 3 :(得分:2)

不使用管道的替代方案:

xargs rm -f <<< $(find . -name ".txt")