I need to delete all compiled data:

  • directories called build,
  • directories called obj,
  • *.so files.

I wrote a command

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

that goes through all the directories recursively and deletes all I need.

Why do I have such an output at the end? Maybe I should write a different command.

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory
  • on what system you are ? you should always use find like this find /search_directory options omiting the search directory is not a good idea – Kiwy Feb 19 '14 at 9:22
  • Automated deleting like this is a bad idea. You could have a script give you candidates, which you should then look at to make sure you are not deleting anything important or necessary to the system. You aren't explicit where you are running this. If you are only doing this in a user space, I suppose it can't do much harm, but you should make sure you are not doing this in a system area accidentally. You definitely want to run such a script as user. – Faheem Mitha Feb 19 '14 at 9:43
  • @Kiwy,@FaheemMitha, the command will only be used in the project directoty; it will not do any harm there. – Maksim Dmitriev Feb 19 '14 at 10:29

Use -prune on the directories that you're going to delete anyway to tell find not to bother trying to find files in them:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

Also note that *.so needs to be quoted as otherwise it may be expanded by the shell to the list of .so files in the current directory.

The equivalent of your GNU -regex-type one would be:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

Note that if you're going to use GNU specific syntax, you might as well use -delete instead of -exec rm -rf {} +. With -delete, GNU find turns on -depth automatically. It doesn't run external commands so in that way, it's more efficient, and also it's safer as it removes the race condition where someone may be able to make you remove the wrong files by changing a directory to a symlink in-between the time find finds a file and rm removes it (see info -f find -n 'Security Considerations for find' for details).

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete
  • -delete also handles things like spaces better – Izkata Feb 19 '14 at 15:33
  • @Izkata, not better than -exec rm -rf {} + which doesn't have issue with those either. – Stéphane Chazelas Feb 19 '14 at 15:43
  • @StephaneChazelas - I'm confused about {} - should they be quoted or not? It seems to work without quotes, but GNU Findutils Manual uses '{}' in example. Could you please clarify? – grebneke Mar 4 '14 at 14:58
  • 1
    @grebneke, I think there's a post somewhere that claims quotes might be needed in very old versions of csh, but I never could verify that claim. They're not needed in any modern shell that I know. They're definitely not required by POSIX. The POSIX examples don't use them. – Stéphane Chazelas Mar 4 '14 at 15:18
  • 3
    And -delete can't be used with directories. – ElementalStorm Jun 16 '16 at 16:21

I guess the reason is that find deletes the directory tree first and tries to check the directory contents which is obviously not the best possible order. You can force find to check the contents first:

find . -depth ...

You should consider using -delete for files and -exec rmdir for directories.


My solution.

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; in the -exec command

  • That's not always going to work, only if no boundary between executions happens inside a deleted directory. – Gilles 'SO- stop being evil' Feb 19 '14 at 23:14
  • @Gilles, what does "boundary between executions" mean? – Maksim Dmitriev Feb 26 '14 at 7:41
  • 1
    -exec … {} + executes the command for multiple files at a time, as many as fit on the command line. If there are too many files (or more precisely if the total length of the paths is too long), find will execute multiple instances of rm, and thus may end up removing a directory that it's traversing. It's just less likely with + than with ;, but + doesn't solve the problem. – Gilles 'SO- stop being evil' Feb 26 '14 at 9:56

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.