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!
If you want to use xargs command to delete these files just pipe it to xargs command with rm function as its argument. In the above case, xargs command will construct separate rm statements for each file name passed to it by the result of find command. That's it.
You can make it do so by using the pipe character '|'. Pipe is used to combine two or more commands, and in this, the output of one command acts as input to another command, and this command's output may act as input to the next command and so on.
The rm command is used to delete files.
The xargs command is used in a UNIX shell to convert input from standard input into arguments to a command. In other words, through the use of xargs the output of a command is used as the input of another command.
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 "\n" "\0" | xargs -0 rm
This time tr
is used to convert all newlines into null characters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With