Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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
share|improve this question
    
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 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 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 at 10:29
add comment

3 Answers

up vote 9 down vote accepted

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
share|improve this answer
    
-delete also handles things like spaces better –  Izkata Feb 19 at 15:33
    
@Izkata, not better than -exec rm -rf {} + which doesn't have issue with those either. –  Stephane Chazelas Feb 19 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 at 14:58
    
@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. –  Stephane Chazelas Mar 4 at 15:18
add comment

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.

share|improve this answer
add comment

My solution.

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

+ vs \; in the -exec command

share|improve this answer
    
That's not always going to work, only if no boundary between executions happens inside a deleted directory. –  Gilles Feb 19 at 23:14
    
@Gilles, what does "boundary between executions" mean? –  Maksim Dmitriev Feb 26 at 7:41
    
-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 Feb 26 at 9:56
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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