Recursively delete empty directories

I recently had to find a neat way to remove all empty directories recursively on a Unix machine. In the world of UNIX you can expect to find a way to do things like this pretty easy. When I started to search for a neat way to do it (rather than reading a bunch of MAN-pages) I came across a really funny story on The Old New Thing. Windows users are so used to having to use an application to do simple things like this, they forget about scripting possibilities. Guess that will change with Power shell.

However this was about how to do this on Unix. Well, this is my solution:

find $1 -type d | sort -r |
while read D
ls -l "$D" | grep -q 'total 0' && rmdir "$D" 2>/dev/null

That script takes one argument; a directory you want to remove if it and all its sub-directories are empty. Any directories encountered where files exists are preserved.

Comments (10)
  1. What if the directory is nonempty but contains only hidden files? Should that be an "ls -la" / total 2?

  2. Actually the "ls | grep" part is some kind of premature optimization (which got in there since it was in the example I looked at). That is why I pipe the output to /dev/null since I don’t want to see the messages about directories not being removed since it is non-empty. Consider the structure "a/b/file". The script above will try to remove "a" (since it contains no files) and fails since "b" is still there.

    A cleaner solution would have only "rmdir $D 2>/dev/null". All this assumes that you have not changed rmdir to an alias like "rm -rf" ofcouse…

  3. ZungBang says:

    find <parent-dir> -depth -type d -empty -exec rmdir -v {} ;

  4. @ZungBang:

    Your example does not know because if I have a structure "A/B" where the folder B is the only content of A your example will only delete B. Also the -empty option is not available on all platforms, for example the standard find on Solaris 8 does not support -empty. Nor does the rmdir on Solaris 8 support "–ignore-fail-on-non-empty" which could be used to supress error messages (instead of piping to /dev/null) from rmdir.

  5. @Magnus:

    Nice since it does not print any error messages for non empty directories. However it assumes perl is installed which might not always be the case.

    Just in case the link disapears, here’s the perl command: perl -MFile::Find -e"finddepth(sub{rmdir},’.’)"

  6. cLive ;-) says:

    @cellfish – no, ZungBang is correct – look up what the "-depth" option does to the recursion order.

  7. @cLive:

    fair enough but still all the options used are not available on all platforms.

  8. Cristian Vidmar says:

    cellfish, your script saved my day but I suggest putting double quotes around $D otherwise the script will fail on directory names with spaces

  9. Good point! I’ve added double quotes in the original post now.

Comments are closed.

Skip to main content