ls | grep | rm -- How to format this command?
I'm trying to delete a bunch of files in a certain directory (on Mac OS X using Terminal)
ls | grep \([1-9]\) | xargs rm
should do the trick, but it doesn't. I'm trying to delete any file with a single digit in parentheses in the filename (duplicates downloaded from the web), but it ends up doing something like this:
> rm: 520syllabus2010: No such file or
> directory rm: (3).pdf: No such file or
> directory
because it doesn't interpret the space correct. It should delete "520syllabus2010 (3).pdf"
What's the proper way of doing this?
Thanks, Jeff
Short version:
rm *\([1-9]\)*
Do not pipe ls
to xargs
. Instead, pipe find ... -print0
to xargs -0
, in order to avoid such problems.
find . -maxdepth 1 -name '*([1-9])*' -print0 | xargs -0 rm
...which can be written as:
find . -maxdepth 1 -name '*([1-9])*' -exec rm {} \;
and:
find . -maxdepth 1 -name '*([1-9])*' -delete
which can further be shortened to just rm
with a wildcard.
Normally, ls
and find
separate file names with newlines, but xargs
splits its input by newline or space, resulting in the behavior you see.
It's possible tell xargs
to split only by newline, but files can have newlines in their names too. In fact, on Linux and BSD, the only disallowed character is the "null" or zero byte – so it's what you should use in such cases.
In example 2 above, -print0
tells find
to separate filenames with a null byte; same for xargs -0
. (A few other tools also have similar options, such as sort -z
or grep -zZ
.)
The "short version" uses a simple shell wildcard ("pattern" in bash
manual – see section "Pathname Expansion").