我想制作一个Ruby程序,将当前目录中的图像分类到不同的子文件夹中,例如:
tree001.jpg, ... tree131.jpg -> to folder "tree"
apple01, ... apple20.jpg -> to folder "apple"
plum1.jpg, plum2.jpg, ... plum33.jpg -> to folder "plum"
等等,程序应该通过名称自动识别哪些文件属于一起。我不知道如何实现这个目标。到现在为止,我创建了一个小程序,它将带有命令“Dir”的文件收集到一个数组中,并按字母顺序对其进行排序,以帮助按文件名查找相应的类。有人有个好主意吗?
答案 0 :(得分:0)
查看查找:
http://www.ruby-doc.org/stdlib-2.0/libdoc/find/rdoc/Find.html
或者Dir.glob:
http://ruby-doc.org/core-2.0/Dir.html#method-c-glob
例如:
Dir.glob("*.jpg")
将返回一个可以使用each
迭代的数组。
答案 1 :(得分:0)
假设每个文件名都以非数字字符开头,后跟至少一个数字字符,并且初始的非数字字符定义了您希望文件移动到的目录:
require 'fileutils'
Dir.glob("*").select{|f| File.file? f}.each do |file| # For each regular file
dir = file.match(/[^\d]*/).to_s # Determine destination directory
FileUtils.mkdir_p(dir) # Make directory if necessary
FileUtils.mv(file, dir) # Move file
end
如有必要,将创建目录。您可以在添加文件后再次运行它。例如,如果您稍后添加了文件tree1.txt
并重新运行了该文件,则会将其移至tree/
,其中tree001.jpg
到tree131.jpg
已经存在。
更新:在评论中,您添加了一项要求,即您只想对形成至少10个组的文件执行此操作。以下是一种方法:
require 'fileutils'
MIN_GROUP_SIZE = 10
reg_files = Dir.glob("*").select{|f| File.file? f}
reg_files.group_by{|f| f.match(/[^\d]*/).to_s}.each do |dir, files|
next if files.size < MIN_GROUP_SIZE
FileUtils.mkdir_p(dir)
files.each do |file|
FileUtils.mv(file, dir)
end
end
答案 2 :(得分:0)
我会这样做:
files = %w[
tree001.jpg tree03.jpg tree9.jpg
apple1.jpg apple002.jpg
plum3.jpg plum300.jpg
].shuffle
# => ["tree001.jpg", "apple1.jpg", "tree9.jpg", "plum300.jpg", "apple002.jpg", "plum3.jpg", "tree03.jpg"]
grouped_files = files.group_by{ |fn| fn[/^[a-z]+/i] }
# => {"tree"=>["tree001.jpg", "tree9.jpg", "tree03.jpg"], "apple"=>["apple1.jpg", "apple002.jpg"], "plum"=>["plum300.jpg", "plum3.jpg"]}
grouped_files.each do |grp, files|
Dir.mkdir(grp) unless Dir.exist(grp)
files.each { |f| FileUtils.mv(f, "#{grp}/#{f}") }
end
我无法测试,因为我没有所有文件,也不愿意生成它们。
重要的是group_by
。它可以轻松地对类似命名的文件进行分组,从而轻松浏览它们。
对于您的情况,您需要将files
的作业替换为Dir.glob(...)
或Dir.entries(...)
以获取文件列表。
如果您要将文件路径与文件名分开,请查看File.split
或File.dirname
和File.basename
:
File.split('/path/to/foo')
=> ["/path/to", "foo"]
File.dirname('/path/to/foo')
=> "/path/to"
File.basename('/path/to/foo')
=> "foo"