Ruby: how do I recursively find and remove empty directories?

You have to delete in reverse order, otherwise if you have an empty directory foo with a subdirectory bar you will delete bar, but not foo.

  Dir.glob(dir + "/**/*").select { |d| 
    File.directory?(d)
  }.reverse_each { |d| 
    if ((Dir.entries(d) - %w[ . .. ]).empty?)
      Dir.rmdir(d)
    end
  }

In ruby:

Dir['**/*']                                            \
  .select { |d| File.directory? d }                    \
  .select { |d| (Dir.entries(d) - %w[ . .. ]).empty? } \
  .each   { |d| Dir.rmdir d }

Looking at the examples from kch, dB. and Vishnu above, I've put together a one-liner that I think is a more elegant solution:

Dir['**/'].reverse_each { |d| Dir.rmdir d if Dir.entries(d).size == 2 }

I use '**/' instead of '/**/*' for the glob, which only returns directories, so I don't have to test whether it's a directory later. I'm using reverse_each instead of sort.reverse.each as it's shorter and supposedly more efficient, according to this post. I prefer Dir.entries(d).size == 2 to (Dir.entries(d) - %w[ . .. ]).empty? because it's a little easier to read and understand, although (Dir.entries(d) - %w[ . .. ]).empty? would probably work better if you had to run your script on Windows.

I've tested this quite a bit on Mac OS X and it works well, even with recursive empty directories.

Tags:

Ruby

File