Linux 为什么我不能将查找结果通过管道传送到 rm?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20307299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:29:48  来源:igfitidea点击:

Linux why can't I pipe find result to rm?

linuxbashfindpiperm

提问by user1297061

sorry if this is a noobie question but I can't find a good answer.

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

To find then remove something I can use

找到然后删除我可以使用的东西

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

But why can't I just pipe the results to rm like

但是为什么我不能像管道一样将结果传递给 rm

find . -name ".txt" | rm 

like I would pipe it to grep

就像我会用管道将它传递给 grep

find . -name ".txt" | grep a

I've read from somewhere that rm doesn't take input from stdin and therefore I can't pipe it but what does that mean? When I type in rm a.txt it reads from standard input just like I can grep right? Or is there a difference between stdin and command line. Help!

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

采纳答案by Tim Pierce

To expand on @Alex Gitelman's answer: yes, there's a difference between "standard input" and the command line.

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

When you type rm a.txt b.txt c.txt, the files you list after rmare known as argumentsand are made available to rm through a special variable (called argvinternally). The standard input, on the other hand, looks to a Unix program like a file named stdin. A program can read data from this "file" just as it would if it opened a regular file on disk and read from that.

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

rm, like many other programs, takes its arguments from the command line but ignores standard input. You can pipe anything to it you like; it'll just throw that data away. That's where xargscomes in handy. It reads lines on standard input and turns them into command-line arguments, so you can effectively pipe data to the command line of another program. It's a neat trick.

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

For example:

例如:

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

Note that this will work incorrectly if there are any filenames containing newlines or spaces. To deal with filenames containing newlines or spaces you should use instead:

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

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

This will tell findto terminate the results with a null character instead of a newline. However, grepwon't work as before then. Instead use this:

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

find . -name ".txt" | grep "foo" | tr "\n" "
xargs rm -f <<< $(find . -name ".txt")
" | xargs -0 rm

This time tris used to convert all newlines into null characters.

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

回答by Alex Gitelman

Pipe sends output of first command to the standard input of second. rmdoes not accept standard input so you can't pipe to it. You could use xargsto achieve the same effect. You can find example for xargsspecifically for your case in man page for xargs.

管道将第一个命令的输出发送到第二个的标准输入。rm不接受标准输入,因此您无法通过管道传输到它。你可以用它xargs来达到同样的效果。您可以xargsxargs 的手册页中找到专门针对您的案例的示例。

回答by thom

"why can't I pipe find result to rm?"

“为什么我不能通过管道找到结果到 rm?”

When you pipe something to a program, the pipe replaces the keyboard input. Keep this in mind and ask youself the next question: What would rmdo with a keyboard? Delete your keystrokes ? (a bit silly indeed) Accepting interactive control ? (rmis not interactive except sometimes when it needs confirmation, which indeed can be given by a pipe.)

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

As a matter of fact, when rmis already running, you can't type commands to let it delete files....so you can't do that with a pipe either.

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

If you keep in mind that a pipe replaces the keyboard/screen combination, things will immediately appear more logical.

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

Now the other way around. You can pipe a datastream into grep. Does that mean that you can let grep read the keystrokes from your keyboard as input data instead ?

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

YES! That is actually what it natively (without piping) does.

是的!这实际上是它本身(没有管道)所做的。

(b.t.w. note that you can not pipe nor type the search argument into grep)

(顺便说一句,您不能通过管道输入搜索参数,也不能将搜索参数输入到grep

So now you know why you can'tpipe to rm andexpect it to work as a commandline argument.

所以现在你知道为什么你不能通过管道连接到 rm期望它作为命令行参数工作。

tl;dr :

tl;博士:

Anatomy of a program according to UNIX philosophy:
file in, file out, keyboard in, screen out. -> Pipe does only replace keyboard and screen.

根据 UNIX 哲学剖析程序:
文件输入、文件输出、键盘输入、屏幕输出。-> 管道只替换键盘和屏幕。

回答by Salvatore De Fidio

An alternative without using pipes :

不使用管道的替代方法:

##代码##

回答by user13497656

find . -name ".txt" | grep "foo" | xargs -I{} rm {}

找 。-name ".txt" | grep "foo" | xargs -I{} rm {}