11

I have temp directories full of junk that all start with __temp__ (e.g. __temp__user_uploads), which I want to delete with a cleanup function. My function attempt is to run:

find . -name __temp__* -exec rm -rf '{}' \;

If I run the command and there are multiple __temp__ directories (__temp__foo and __temp__bar), I get the output:

find: __temp__foo: unknown option

If I run the command and there is only 1 __temp__ directory (__temp__foo), it is deleted and I get the output:

find: ./__temp__foo: No such file or directory

Why doesn't the command work, why is it inconsistent like that, and how can I fix it?

1 Answer 1

28

Use a depth-first search and quote (or escape) the shell metacharacter *:

find . -depth -name '__temp__*' -exec rm -rf '{}' \;

Explanation

Without the -depth flag, your find command will remove matching filenames and then try to descend into the (now unlinked) directories. That's the origin of the "No such file or directory" in your single __temp__ directory case.

Without quoting or escaping the *, the shell will expand that pattern, matching several __temp__whatever filenames in the current working directory. This expansion will confuse find, which is expecting options rather than filenames at that point in its argument list.

5
  • 6
    As an efficiency and tightness improvement, assuming GNU utilities (since the OP is on Linux), I'd actually recommend find . -maxdepth 1 -type d -name '__temp__*' -print0 | xargs -0 rm -rf.
    – pilcrow
    Commented Sep 19, 2012 at 3:46
  • +1 for suggesting xargs instead of -exec Commented Sep 19, 2012 at 7:13
  • @AshishKumar - why +1 for xargs? Is -exec not a good feature of find? pilcrow, thanks for the explanation!
    – orokusaki
    Commented Sep 19, 2012 at 15:19
  • 2
    @orokusaki: -exec isn't bad per se, but it will fire once for every file that matches: rm foo, then rm bar, and so on. xargs will pass many filenames as arguments to its child commands, and so is more efficient: rm foo bar ... Unless you have thousands of files, xargs will probably invoke only one instance of rm
    – pilcrow
    Commented Sep 19, 2012 at 15:44
  • 2
    @orokusaki: this is correct, -exec will execute once each time a file is found, which will then continuously fork the external command, "rm" in this case. however, if you use "| xargs" then find will locate all files, kind of store them in an array and then the whole bunch of array will be passed to "rm" called by "xargs", e.g. rm -fr foo bar qux spam eggs etc. +1 once again for pilcrow for the explanation of xargs. Commented Sep 24, 2012 at 20:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.