236

I'm trying to understand the difference between these two commands:

sudo find / -name .DS_Store -delete

and

sudo find / -name ".DS_Store"  -exec rm {} \;

I noticed that the execmethod is preferred. Why? Which one is safer/faster/better? I've used both on my Macbook and everything appears to work well.

222

-delete will perform better because it doesn't have to spawn an external process for each and every matched file.

It is possible that you may see -exec rm {} \; often recommended because -delete does not exist in all versions of find. I can't check right now but I'm pretty sure I've used a find without it.

Both methods should be "safe".

EDIT per comment from @doitmyway: make sure you match on the name and then delete, not the other way around (delete, then match). Otherwise every file will be deleted, whether it matches or not. I.e., DO NOT do this: find / -delete -name .DS_Store.

A common method for avoiding the overhead of spawning an external process for each matched file is:

find / -name .DS_Store -print0 | xargs -0 rm

(but note that there is a portability problem here too: not all versions of find have -print0!)

  • 1
    I see. I've also read that using the -delete switch before -name deletes the specified file tree, so I guess I have to be careful. – Onion Nov 13 '14 at 18:56
  • 7
    On recent find you can use -exec rm {} + to remove all matched files with single rm command. – jimmij Nov 13 '14 at 18:59
  • 3
    .DS_Store doesn't contain any special characters at all, so the quotes are unnecessary and change nothing in this case. – Celada Nov 13 '14 at 19:09
  • 1
    Basically only whitespace (spaces, tabs, maybe others) is the only thing that causes an unquoted string to be interpreted as two separate command line arguments, but that's not all you have to sorry about when deciding whether or not to quote. You have to worry about all shell metacharacters like ; or | or > or < and `` and many others which have special meaning to the shell unless quoted. – Celada Nov 13 '14 at 21:41
  • 1
    @MarcoMarsala xargs takes care of the limited-size argument list problem transparently by breaking it up into multiple invocations of the command. – Celada Oct 22 '15 at 19:36
24

Assuming .DS_Store represent files and not directories, the most portable still fast way to do it would be:

sudo find / -name .DS_Store -exec rm {} +

The only risk is for sudo not to be available but it is quite low nowadays.

-delete demands GNU find which is not always present.

The command termination + instead of \; highly optimizes the exec clause by not running the rm command for each and every .DS_Store present on the file system.

15

For a machine such as your macbook you won't find much difference in performance between the two commands. However, if you look at the -exec version you can see a subtle difference:

sudo find / -iname ".file-to-delete"  -exec rm {} \;

This means that you will find all those files with name ".file-to-delete". However this search might return some unwanted false positives. When doing something with sudo you should be a bit more careful. The advantage of using -exec rm {} is that you can pass arguments to rm like this:

sudo find / -iname "*~"  -exec rm -i {} \;

In this example I want to remove those backup files that emacs makes. However that tilde could be in some obscure file that I don't know about and could be important. Plus I want to confirm the delete. So I put the option '-i' on the rm command. This will give me an interactive delete.

Also you can refine the usage of rm to delete directories as well as files:

find /usr/local/share/ -iname "useless" -exec rm -r {} \;

In brief, the -exec gives you a bit more control over the actual command that removes the found item. The advantage is that you use one tool to find the files, another tool to remove them. Also not every version of the find utility has the -delete option. So better to use each tool for its proper job. This is the unix philosophy - one tool, one job, use them together to do what you need to do.

  • 2
    See also -ok rm {} \; in place of -exec rm {} \; for interactive confirmation. – Kusalananda Jun 27 '18 at 9:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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