In an old version of Unix, the rm command would delete directories if they were empty. From the Research Unix Eighth Edition man page for rm: "If an entry is a directory it is removed only if empty." I like this behaviour, so I've got this alias in my /etc/profile: alias rm='rm -d' I'm using the GNU coreutils version of rm, in which -d tells rm to go ahead and remove directories if they're empty.

So far so good. This alias allows me to use rm like the old days. However, I'd like to take it a step further. I'd like rm to delete a directory even if the directory contains other directories, so long as directories are the only thing there. It doesn't matter how deep the directory structure goes, as long as there aren't any files in there, just empty (once you get to the bottom) directories, I'd like rm to remove them all.

Could this be written as an alias which would still function as the regular rm and delete any files passed to it?

  • How about rmdir -p?
    – Kevin
    Dec 9, 2013 at 0:45
  • Thanks for the suggestion Kevin, but this isn't quite the behaviour I'm looking for. If I run mkdir -p a/b1/c2 && mkdir -p a/b2/c2; rmdir -p a/b1/c1;, I'm still left with a, a/b2, and a/b2/c2. What I'd like is to pass just the top level (a in this case) to rm, and have everything below it removed. Dec 9, 2013 at 0:57

1 Answer 1


You want to traverse a directory tree and see if it contains anything other than a directory. This is beyond rm's capabilities. You need other tools such as find. You can delete the empty directories under a given directory this way (-depth causes parent directories that become empty to be deleted as well):

find "$x" -depth -type d -exec rmdir {} +

Here is a function which, for each argument, deletes the argument if it is a non-directory file or a directory tree not containing anything other than directories. Note that this function isn't atomic: if one of the arguments changes while it's running, you may end up with an error message, but it's safe in that it won't delete any non-directory inside a directory passed as argument.

rm () {
  for x; do
    case $x in -*) x=./$x;; esac
    if [ -d "$x" ]; then
      if [ -n "$(find "$x" ! -type d | head -n 1)" ]; then
        echo 1>&2 "$x: non-empty directory tree"
        find "$x" -depth -exec rmdir {} +
        if [ -d "$x" ]; then ret=2; fi
      command rm "$x" || [ $ret -gt 1 ] || ret=2
  return $ret

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .