我正在尝试编写一些ruby,它会递归搜索给定目录中的所有空子目录并删除它们。
思想?
注意:如果可能的话,我想要一个脚本版本。这既是实际需要,也是帮助我学习的东西。
答案 0 :(得分:16)
在红宝石中:
Dir['**/*'] \
.select { |d| File.directory? d } \
.select { |d| (Dir.entries(d) - %w[ . .. ]).empty? } \
.each { |d| Dir.rmdir d }
答案 1 :(得分:7)
查看kch,dB的例子。和上面的Vishnu一起,我认为这是一个更优雅的解决方案:
Dir['**/'].reverse_each { |d| Dir.rmdir d if Dir.entries(d).size == 2 }
我使用'**/'
而不是'/**/*'
作为glob,它只返回目录,因此我不必测试它是否是以后的目录。根据{{3}},我使用reverse_each
代替sort.reverse.each
,因为它更短,据说效率更高。我更喜欢Dir.entries(d).size == 2
到(Dir.entries(d) - %w[ . .. ]).empty?
,因为它更容易阅读和理解,但如果您必须在Windows上运行脚本,(Dir.entries(d) - %w[ . .. ]).empty?
可能会更好。
我在Mac OS X上对此进行了相当多的测试,即使使用递归的空目录也能正常运行。
答案 2 :(得分:3)
你必须以相反的顺序删除,否则如果你有一个带有子目录栏的空目录foo,你将删除bar,但不会删除foo。
Dir.glob(dir + "/**/*").select { |d|
File.directory?(d)
}.reverse_each { |d|
if ((Dir.entries(d) - %w[ . .. ]).empty?)
Dir.rmdir(d)
end
}
答案 3 :(得分:2)
为什么不使用shell?
找到。 -type d -empty -exec rmdir'{}'\;
完全符合你的要求。
答案 4 :(得分:2)
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}
以提高效率
答案 5 :(得分:1)
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
答案 6 :(得分:0)
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
答案 7 :(得分:0)
我在OS X上测试了这个脚本,但是如果你在Windows上,则需要进行更改。
您可以使用Dir#entries找到目录中的文件,包括隐藏文件。
此代码将删除删除任何子目录后变为空的目录。
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
答案 8 :(得分:0)
对于纯壳解决方案,我发现这非常有用
find "$dir" -depth -type d |
while read sub; do
[ "`cd "$sub"; echo .* * ?`" = ". .. * ?" ] || continue
echo rmdir "$sub"
#rmdir "$sub"
done
但是如果您已经安装了gnu-find(还不是通用的)...
find . -depth -type d -empty -printf "rmdir %p\n"
这与xargs一起使用find ...
find . -depth -type d -print0 |
xargs -0n1 sh -c '[ "`cd "$0"; echo .* * ?`" = ". .. * ?" ] &&
echo "rmdir $0";'