You mentioned find -empty, so your find is probably GNU find. In this answer I will use several non-portable features of GNU find.
Please test my solution in an expendable directory first. The solution is:
find . -type d \( -empty -delete -o -exec sh -c ' special=".directory" test -f "$1/$special" \&& find "$1" -mindepth 1 -maxdepth 1 ! -name "$special" | { ! grep -q .; } \&& rm "$1/$special"' find-sh {} \; -delete \) -printIt works like this:
Because
-deleteimplies-depth, the command will process a directory only after processing everything in it. This is good, as we do want it to process and possibly delete deeper subdirectories first, so when it gets to a parent, there is a chance it has just became empty or almost empty.The command acts on files of the type directory (
-type d).If the currently considered directory is empty, the command tries to delete it (
-empty -delete).Otherwise (i.e. if the directory is not empty) a snippet of shell code is executed. Frankly it will be executed also if the directory is empty and the deletion fails; but in this case the snippet should be harmless, so it's OK.
The shell code uses
&&, so each next step is executed if and only if its preceding step succeeded. The steps are:- Test if there is a regular file with our "special" name there (
test -f …). - Start finding files directly in the directory (
-mindepth 1 -maxdepth 1) with names different than the "special" name. If the output from the innerfindis empty thengrep -q .will exit with non-zero exit status, so! grep …will give us a success… - And then
rmwill be executed to remove the "special" file.
Only if this
rmis successful, the-exectest will be considered true for the directory and the last-deletewill be attempted.- Test if there is a regular file with our "special" name there (
-printwill print pathnames of directories for which-delete(the first or the second one) succeeded.
Notes:
- In my tests
-deletedid not delete.even when it was empty, although it formally succeeded. -nametakes a pattern. In general, if the "special" name contains*,?or[then you need to adjust the code..directoryis safe in this matter.