Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

bash - 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

find . -name ".txt" | rm 

like I would pipe it to 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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

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). 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, 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 xargs comes 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.

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. However, grep won't work as before then. Instead use this:

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

This time tr is used to convert all newlines into null characters.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...