Delete files not matching pattern using xargs
The following command is from https://www.tecmint.com/xargs-command-examples/ the example #9. It is to delete files not matching *gz from current directory.
$ find . -type f -not -name '*gz' -print0 | xargs -0 -I {} rm -v {}
What are the purpose of -print0
arg of find
command and -0
and -I {}
args of xargs
command? Why are they needed? Thanks!
-print0
tells find
to output its results separated by null bytes instead of the usual newline characters. This is necessary if the filenames do (or may in the future) contain newline characters themselves.
You then need to tell xargs
to expect null-delimited data coming down the pipe - that's what the -0
is for. So it's necessary here when using -print0
on the LHS.
Meanwhile {}
is a replacement string - when you use -I {}
, each {}
in the following command will be replaced by an input item. It's only really necessary when you need control over where the item appears in the following command line (and has the side-effect of running a single invocation for each item, equivalent to adding -L 1
). IMHO it's not necessary here, and makes the solution inefficient since it runs rm
once for each file found, instead of in batches.
Note that find
has a -exec
option and a -delete
option that both avoid the issue of writing / reading delimited data altogether:
find . -type f -not -name '*gz' -exec rm -v {} +
or
find . -type f -not -name '*gz' -print -delete
(the -print
here to give similar functionality as the -v
option to rm
).