[英]Linux why can't I pipe find result to rm?
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?我从某处读到 rm 不接受来自 stdin 的输入,因此我无法通过管道传输它,但这意味着什么? When I type in rm a.txt it reads from standard input just like I can grep right?
当我输入 rm a.txt 时,它从标准输入中读取,就像我可以 grep 一样吗? Or is there a difference between stdin and command line.
或者标准输入和命令行之间有区别。 Help!
帮助!
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 rm
are known as arguments and are made available to rm through a special variable (called argv
internally).当您键入
rm a.txt b.txt c.txt
,您在rm
之后列出的文件称为参数,并通过特殊变量(内部称为argv
)提供给 rm。 The standard input, on the other hand, looks to a Unix program like a file named stdin
.另一方面,标准输入看起来像一个名为
stdin
的文件的 Unix 程序。 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
, like many other programs, takes its arguments from the command line but ignores standard input. rm
与许多其他程序一样,从命令行获取参数但忽略标准输入。 You can pipe anything to it you like;你可以把任何你喜欢的东西用管道输送到它; it'll just throw that data away.
它只会把这些数据扔掉。 That's where
xargs
comes in handy.这就是
xargs
派上用场的地方。 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.
这是一个巧妙的技巧。
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 find
to terminate the results with a null character instead of a newline.这将告诉
find
用空字符而不是换行符终止结果。 However, grep
won't work as before then.但是,
grep
不会像以前那样工作。 Instead use this:而是使用这个:
find . -name ".txt" | grep "foo" | tr "\n" "\0" | xargs -0 rm
This time tr
is used to convert all newlines into null characters.这次
tr
用于将所有换行符转换为空字符。
"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
rm
do with a keyboard?记住这一点并问自己下一个问题:
rm
会用键盘做什么? Delete your keystrokes ?删除您的按键? (a bit silly indeed) Accepting interactive control ?
(确实有点傻)接受交互式控制? (
rm
is not interactive except sometimes when it needs confirmation, which indeed can be given by a pipe.) (
rm
不是交互式的,除非有时需要确认,这确实可以由管道给出。)
As a matter of fact, when rm
is 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
.您可以将数据流通过管道传输到
grep
。 Does that mean that you can let grep read the keystrokes from your keyboard as input data instead ?这是否意味着您可以让 grep 将键盘上的击键读取为输入数据?
YES!是的! That is actually what it natively (without piping) does.
这实际上是它本身(没有管道)所做的。
(btw note that you can not pipe nor type the search argument into grep
) (顺便说一句,您不能通过管道输入搜索参数,也不能将搜索参数输入
grep
)
So now you know why you can't pipe to rm and expect it to work as a commandline argument.所以现在你知道为什么你不能通过管道连接到 rm并期望它作为命令行参数工作。
tl;dr : tl;博士:
Anatomy of a program according to UNIX philosophy:根据 UNIX 哲学对程序进行剖析:
file in, file out, keyboard in, screen out.文件输入,文件输出,键盘输入,屏幕输出。 -> Pipe does only replace keyboard and screen.
-> 管道只替换键盘和屏幕。
Pipe sends output of first command to the standard input of second.管道将第一个命令的输出发送到第二个的标准输入。
rm
does not accept standard input so you can't pipe to it. rm
不接受标准输入,因此您无法通过管道传输到它。 You could use xargs
to achieve the same effect.您可以使用
xargs
来达到相同的效果。 You can find example for xargs
specifically for your case in man page for xargs .您可以在
xargs
手册页中找到专门针对您的案例的xargs
示例。
不使用管道的替代方法:
xargs rm -f <<< $(find . -name ".txt")
find .找到。 -name ".txt" |
-name ".txt" | grep "foo" |
grep "foo" | xargs -I{} rm {}
xargs -I{} rm {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.