Finding empty directories recursively

(I don't have a Solaris machine handy so am working from manpages, so you may have to play with the syntax a bit here.)

You can make use of the fact that any empty directory will have a link count of 2 (only the directory name itself, dir, plus its own dir/., link to it); in UNIX, it's illegal to (hard) link to a directory except in the course of adding it to (a single) directory entry or having directory entries added to it, so this is an invariant. (Basically1.)

Solaris doesn't support the -empty option, but it does support the -links <n> option to search for things with exactly n links. So the command you want (I think; see below) is:

find /home/.../Desktop -type d -links 2 -print

by the way...

Your use of the word "recursively" is a bit ambiguous, so please note that this won't find directories containing nothing but empty directories (or so on, recursively). If you want that, the question is very easy if you want to identify them in order to delete them. Just repeatedly run the command above, adding -exec rmdir {} \; until none are left; each time you run it, you'll remove the parents of trees one level deeper, so it shouldn't take many runs unless you have a very deep directory tree consisting of nothing but otherwise empty directories. (Depending on how Solaris find(1) works, I think you can also run find . -type d -exec rmdir -p {}; just once (the -p option tells rmdir(1) that it can remove directories containing directories that are empty), but because it will then try to traverse dirs that have been deleted, you'll get a bunch of error messages you can ignore mixed in with ones you might care about, so I'd do it this iterative way instead.)

(Note that the -depth option of find(1) does not help here, as files are stat()'d too early for the link count to be updated. Otherwise, you could run find -depth $dir -type d -links 2 -exec rmdir {} \; and one run would be sufficient.)

If you want to identify both "intrinsically empty" directories and directories containing nothing but empty directories (or so on, recursively) without removing them, it's more complex. I assume a single command line is possible, but it will be a beast (one I'm sure someone else will take a stab at later), at least without resorting to perl or a crazy sed/awk incantation.

But what I'd do is copy the directory tree somewhere, say /tmp/tree-copy, then run the command

find /tmp/tree-copy -type d -links 2 -print -exec rmdir {} \; | tee -a /tmp/empty-dirlist

repeatedly until it produces no more output. (The tee -a lets you see the output, but also appends it to the file /tmp/empty-dirlist.)

You'll then want to remove the /tmp/tree-copy or whatever from each line of the file;

perl -i -lpe 's{^/tmp/tree-copy/}{}' /tmp/empty-dirlist

will work for that, or you can use your text editor. Voilà!, a list of the empty directories, where "empty" is defined as "containing nothing but directories". (You could also put the perl, or sed or whatever, into the pipeline before the tee -a if you like.)


  1. Before some wag points this out, this is not necessarily true for filesystem mount points; filesystem managers on some OSes are free to use the link count of the mount point for their own private use, so you'll frequently see mountpoint directories, empty or not, with link counts of 1 (illegal for directories in other circumstances), 2, or something else meaningful but not related to its actual link count. So if you're going to do the above you should check that you're not potentially traversing mount points, as it's possible, though unlikely, that one of them will have a link count of 2.