0

cannot delete my own question, overwrite instead

1
  • I managed to delete everything myself using vi to edit the temporary file, after discovering that there were also filenames which contained parenthesis -- which the shell also does not like....
    – user264785
    Jan 24, 2014 at 22:15

2 Answers 2

1

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 finds 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
4
  • … 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.
    – slhck
    Jan 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.
    – JdeBP
    Jan 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.
    – slhck
    Jan 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. (-:
    – JdeBP
    Jan 24, 2014 at 19:56
0

What's wrong with

rm *\ *

or

rm *' '*

or

rm *" "*

You might try 'ls' before doing 'rm' so you are sure what you are doing.

1
  • It's not recursive, perhaps that's why the OP didn't use rm. (Not that it cannot be done, but…)
    – slhck
    Jan 24, 2014 at 19:17