From the find manpage:
-depth Process each directory’s contents before the directory itself. The -delete action also implies -depth.
With
find . -type d -depth -empty -exec rmdir "{}" \;
find starts in the current directory, and looks for all files and directories contained therein (and in children etc.); it then processes each one, starting with the contents of a directory before processing the parent directory. Imagine the following tree:
.
├── a
│ ├── c
│ └── d
│ └── e
└── b
find . -depth shows the order in which this will be processed:
./a/c
./a/d/e
./a/d
./a
./b
.
As you can see, the children are listed before the parents. In a more complex find command, the actions would be applied to children before parents; in the example you give, empty leaf directories will be processed first, and if they’re empty, deleted; then their parents will be processed, and in turn if they’re empty (which might be the case since their empty children have been deleted), deleted too, and so on all the way back to the current directory.
If you omit -depth, find processes files in enumeration order, for example
.
./a
./a/c
./a/d
./a/d/e
./b
So . is processed first; it’s not empty so it’s left alone. Then a, and the same applies. Then a/c; that gets deleted since it’s empty. a/d is left alone, a/d/e is deleted, as is b. But find doesn’t revisit the directories it’s already processed, so a and a/d remain even though we want them to be deleted.
-exec rmdir {} +instead of-exec rmdir {} \;to avoid running onermdirper directory as that would delay the running sofindwould not delete the parent as it would not be empty at the time of the check (it would become empty later whenrmdiris run when enough arguments have been accumulated). With somefindimplementations including yours, you cause use-delete(which implies-depthas noted, sofind . -type d -empty -deletewould be enough). That saves a rmdir execution and also removes some race conditions. – Stéphane Chazelas Dec 08 '17 at 16:08