The find / xargs Linux command-pipe
My task at hand is to delete all backup files ("*~") located anywhere in my home directory hierarchy.
$ find /home/peter -name *~ |xargs rm
This works reasonably well, but some targeted backup files are actually not deleted, namely:
In addition, the xargs command handles zero argument poorly. If no match is found by the find command, xargs is not smart enough to terminate right away, but will still try to execute the target command (rm) in some way.
$ find /home/peter -name no-such-thing* |xargs rm
rm: missing operand
Symbolic Links
find does not follow symbolic links, by default. To make it follow symbolic links, add the -L parameter.
$ find -L /home/peter -name *~ |xargs rm
Names with spaces
xargs splits up its input arguments at spaces (and newlines). If a file name (or path name) has spaces in it, e.g., "can not do this.pdf", xargs will misinterpret it and thinks there are multiple files.
The solution is to invoke xargs with the -0 (zero) parameter. xargs will separate filenames by NUL instead of whitespace. Also, the find command needs the -print0 parameter: this puts a NUL between filenames instead of a newline.
Note that the -print0 parameter must be put last in find.
$ find /home/peter -name *~ -print0 |xargs -0 rm
Zero argument
Use the -r flag with xargs. If stdin is empty, xargs will not run the command, and exit.
Putting it altogether, the command I will use for my task is:
$ find -L /home/peter -name *~ -print0 |xargs -0 -r rm
$ find /home/peter -name *~ |xargs rm
This works reasonably well, but some targeted backup files are actually not deleted, namely:
- backup files in a sub-directory that is symbolically linked.
- backup files that have spaces in their file name or path name.
In addition, the xargs command handles zero argument poorly. If no match is found by the find command, xargs is not smart enough to terminate right away, but will still try to execute the target command (rm) in some way.
$ find /home/peter -name no-such-thing* |xargs rm
rm: missing operand
Symbolic Links
find does not follow symbolic links, by default. To make it follow symbolic links, add the -L parameter.
$ find -L /home/peter -name *~ |xargs rm
Names with spaces
xargs splits up its input arguments at spaces (and newlines). If a file name (or path name) has spaces in it, e.g., "can not do this.pdf", xargs will misinterpret it and thinks there are multiple files.
The solution is to invoke xargs with the -0 (zero) parameter. xargs will separate filenames by NUL instead of whitespace. Also, the find command needs the -print0 parameter: this puts a NUL between filenames instead of a newline.
Note that the -print0 parameter must be put last in find.
$ find /home/peter -name *~ -print0 |xargs -0 rm
Zero argument
Use the -r flag with xargs. If stdin is empty, xargs will not run the command, and exit.
Putting it altogether, the command I will use for my task is:
$ find -L /home/peter -name *~ -print0 |xargs -0 -r rm