要查找然后删除我可以使用的内容
find . -name ".txt" -exec rm "{}" \;
但为什么我不能把结果传递给rm像
find . -name ".txt" | rm
像我将它传递给grep一样
find . -name ".txt" | grep a
我从某个地方读过rm不接受来自stdin的输入,因此我无法管道但是这意味着什么?当我输入rm a.txt时,它会从标准输入中读取,就像我可以直接读取一样吗?或者stdin和命令行之间有区别。救命啊!
答案 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")