Ruby:我如何递归查找和删除空目录?

我正在尝试编写一些ruby,它会递归搜索给定目录中的所有空子目录并删除它们。

思考?

注意:如果可能的话,我想要一个脚本版本。 这既是实际需要,也是帮助我学习的东西。

在ruby中:

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

看一下kch,dB的例子。 和上面的Vishnu,我已经整理了一个单线程,我认为这是一个更优雅的解决方案:

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

我使用'**/'代替'/**/*'作为glob,它只返回目录,所以我不必测试它是否是一个目录。 根据这篇文章 ,我正在使用reverse_each而不是sort.reverse.each因为它更短,据说效率更高。 我更喜欢Dir.entries(d).size == 2(Dir.entries(d) - %w[ . .. ]).empty? 因为它更易于阅读和理解,但是(Dir.entries(d) - %w[ . .. ]).empty? 如果必须在Windows上运行脚本,可能会更好。

我已经在Mac OS X上对此进行了相当多的测试,它运行良好,即使使用递归的空目录也是如此。

您必须以相反的顺序删除,否则如果您有一个带有子目录栏的空目录foo,您将删除bar,但不会删除foo。

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

为什么不使用shell?

找 。 -type d -empty -exec rmdir'{}’\;

完全符合你的要求。

 Dir['/Users/path/Movies/incompleteAnime/foom/**/*']. \ select { |d| File.directory? d }. \ sort.reverse. \ each {|d| Dir.rmdir(d) if Dir.entries(d).size == 2} 

就像第一个例子一样,但第一个例子似乎没有处理递归位。 排序和反向确保我们首先处理最嵌套的目录。

我想sort.reverse可以写成sort {|a,b| b <=> a} sort {|a,b| b <=> a}提高效率

 module MyExtensions module FileUtils # Gracefully delete dirs that are empty (or contain empty children). def rmdir_empty(*dirs) dirs.each do |dir| begin ndel = Dir.glob("#{dir}/**/", File::FNM_DOTMATCH).count do |d| begin; Dir.rmdir d; rescue SystemCallError; end end end while ndel > 0 end end end module ::FileUtils extend FileUtils end end 

我在OS X上测试了这个脚本,但是如果你在Windows上,你需要进行更改。

您可以使用Dir#条目在目录中找到文件,包括隐藏文件。

删除任何子目录后,此代码将删除变为空的目录。

 def entries(dir) Dir.entries(dir) - [".", ".."] end def recursively_delete_empty(dir) subdirs = entries(dir).map { |f| File.join(dir, f) }.select { |f| File.directory? f } subdirs.each do |subdir| recursively_delete_empty subdir end if entries(dir).empty? puts "deleting #{dir}" Dir.rmdir dir end end 
 Dir.glob('**/*').each do |dir| begin Dir.rmdir dir if File.directory?(dir) # rescue # this can be dangereous unless used cautiously rescue Errno::ENOTEMPTY end end