I'm writing a command line script to 'unpack' folders with .svg files from downloads. I've copied the required files to a specific directory and now I need to delete all the directories with .svg files in them because they are full of other formats and licences, which I don't need. How do I do this?


GNUly, that could be:

LC_ALL=C find . -name '*.svg' -type f -printf '%h\0' |
  LC_ALL=C sort -zu |
  xargs -r0 echo rm -rf

Where find reports the dirname of all .svg regular files, sort -zu removes duplicates, and xargs rm removes them.

That's not terribly efficient in that it keeps looking for .svg files in children of a given directory even after .svg file have been found in it.

Note that if the current directory contains .svg files, rm will refuse to delete it (as a safeguard on rm -rf . to work around a misfeature in some shells where rm -rf .* includes . and .. in the expansion of .*).

You can work around that by replacing . with "$PWD" above.

Remove the echo when you're satisfied it will do what you want.

With the bosh shell, you could do it more efficiently with its builtin find:

has_svg() {
  find "$@" -maxdepth 1 -name '*.svg' -type f -call return 0 \;
  return 1

find . -type d -call 'has_svg "$1"' {} \; -prune -exec echo rm -rf {} +
  • Thanks! I tried the find command before, but I probably did something wrong earlier. It seems to be one of the slightly more confusing ones. Jul 23 '20 at 7:01

Using GNU find we employ find within find to first look at a dir starting from the lower levels and then check whether that dir comprises atleast one .svg file. We delete such dirs.

$ find . -depth  ! -name . -type d  \
    -exec sh -c '
      for d do
        test "x$(find "$d/." -maxdepth 1 -type f -name "*.svg" -print -quit)" != "x" &&
          set -- "$@" "$d"
      shift "$N"; rm -rf ${1+"$@"}
 ' find-sh {} +
  • Fixed the issue. Thanks. Jul 23 '20 at 22:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.