cannot delete my own question, overwrite instead
2 Answers
Alright, let's do this progressively.
And let's presume that you really do want to look in subdirectories as well, even though that's only implied in your question.
As a first pass, this is just a simple exercise in passing a wildcard to the find
command, remembering to quote it of course, and executing the rm
command for every file found:
find $BASE_DIR/ -name '* *' -exec rm {} \;
But of course that's dreadfully inefficient. It starts up a whole rm
process for each individual file. So while we could take a short detour through \+
that's not where we are going to end up, so let's take the shorter route and bring in xargs
to batch up the filenames into groups:
find $BASE_DIR/ -name '* *' -print | xargs rm
But that has two security holes. First, if any filename found happens to begin with a minus sign rm
will treat it as a command-line option rather than a filename, and generate an error. (The -exec rm {}
version also has this problem.) Second, filenames containing whitespace will not be handled properly by xargs
, as you've noticed. So a further iteration is to make this a little more bulletproof:
find $BASE_DIR/ -name '* *' -print0 | xargs -0 rm --
And, of course, there are the interactive features of rm
that you probably don't want:
find $BASE_DIR/ -name '* *' -print0 | xargs -0 rm -f --
The -print0
and -0
options are not standard, but the GNU find
and xargs
, as well as the FreeBSD find
and xargs
, understand them. However, even this is improvable. We don't need to spawn any extra processes at all. The GNU and FreeBSD find
s can both invoke the unlink(2)
system call directly:
find $BASE_DIR/ -name '* *' -delete
As a last preventative measure to stop you doing more than you intended in certain circumstances, remember that the filesystem can contain more than just regular files:
find $BASE_DIR/ -name '* *' -type f -delete
-
… so basically, what I wrote ;) Nice explanation, although I'd recommend putting the most secure variant at the top of the post, not at the bottom.– slhckJan 24, 2014 at 19:17
-
No: what I wrote, back on 2014-01-09, tracking the 1 character difference in the question and the slight changes necessary for the C shell.– JdeBPJan 24, 2014 at 19:38
-
True, I just saw that I answered that as well. Which kind of makes it a duplicate, especially since the answer is exactly the same, just swapping one character.– slhckJan 24, 2014 at 19:47
-
I did wonder why you'd not marked it as a duplicate. I held off doing so thinking that you must have had your reasons. I nearly put "Duplicate question therefore duplicate answer." at the top, though. (-:– JdeBPJan 24, 2014 at 19:56
What's wrong with
rm *\ *
or
rm *' '*
or
rm *" "*
You might try 'ls' before doing 'rm' so you are sure what you are doing.
-
It's not recursive, perhaps that's why the OP didn't use
rm
. (Not that it cannot be done, but…)– slhckJan 24, 2014 at 19:17