Quantcast
Channel: User Kamil Maciorowski - Super User
Viewing all articles
Browse latest Browse all 837

Answer by Kamil Maciorowski for Delete directories containing only .directory files

$
0
0

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 \) -print

It works like this:

  • Because -delete implies -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 inner find is empty then grep -q . will exit with non-zero exit status, so ! grep … will give us a success…
    • And then rm will be executed to remove the "special" file.

    Only if this rm is successful, the -exec test will be considered true for the directory and the last -delete will be attempted.

  • -print will print pathnames of directories for which -delete (the first or the second one) succeeded.

Notes:

  • In my tests -delete did not delete . even when it was empty, although it formally succeeded.
  • -name takes a pattern. In general, if the "special" name contains *, ? or [ then you need to adjust the code. .directory is safe in this matter.

Viewing all articles
Browse latest Browse all 837

Trending Articles