Ruby程序按名称将图像分类到不同的目录中?

时间:2013-06-27 22:27:00

标签: ruby sorting design-patterns classification

我想制作一个Ruby程序,将当前目录中的图像分类到不同的子文件夹中,例如:

tree001.jpg, ... tree131.jpg -> to folder "tree"
apple01, ... apple20.jpg -> to folder "apple"
plum1.jpg, plum2.jpg, ... plum33.jpg -> to folder "plum"

等等,程序应该通过名称自动识别哪些文件属于一起。我不知道如何实现这个目标。到现在为止,我创建了一个小程序,它将带有命令“Dir”的文件收集到一个数组中,并按字母顺序对其进行排序,以帮助按文件名查找相应的类。有人有个好主意吗?

3 个答案:

答案 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.jpgtree131.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.splitFile.dirnameFile.basename

File.split('/path/to/foo')
=> ["/path/to", "foo"]
File.dirname('/path/to/foo')
=> "/path/to"
File.basename('/path/to/foo')
=> "foo"