メモ

Perl, Python, Ruby の比較
ここの Ruby 用のプログラムを、勉強のために写経する。細部は勝手に好みの流儀に改めてある。元のプログラムを書かれた方には感謝します。

require "fileutils"

class Photo
  # global parameters  
  REG_FILE = Regexp.new("\\.(gif|bmp|jpe?g|tiff?|wav|mov)$", Regexp::IGNORECASE)
  REG_DIR = Regexp.new('^photo[0-9][0-9]$')
  
  def initialize
    @H = Hash.new
  end
      
  # HD 側に何個の photoNN フォルダーがあるかを返します。
  def n_photo_dir(d)
    Dir.entries(d).select {|x| FileTest.directory?(File.join(d, x)) and REG_DIR.match(x)
     }.map {|x| x[5..6].to_i}.inject(0) {|x, y| max(x, y)}
  end
  
  # メディアに保存されている写真ファイルの一覧をフォルダーごとにまとめて返します
  # 再帰的にファルダーのツリーを下っていき、写真ファイルの一覧をフォルダー名をキーとしてハッシュ表に登録します
  def search_media(d)
    Dir.chdir(d)
    ls = Dir.glob("*")
  
    ls_f = ls.select {|x| FileTest.file?(File.join(d, x)) and REG_FILE.match(x)}
    
    @H[d] = ls_f unless ls_f.empty? 
    ls.map {|x| File.join(d, x)}.select {|x| FileTest.directory?(x)}.each {
     |x| search_media(x)}
  end
  
  # 写真ファイルをメディアから HD にコピーします
  def move_photos(d0, d1)
    dir_of_month = File.join(d1, Time.now.strftime("%y-%m"))
    search_media(d0)
    total_files = @H.values.map {|x| x.size}.inject(0) {|result, item| result + item }
    
    if total_files == 0
      puts "no photos, give return"
      STDIN.readline
      abort
    end
    
    Dir.mkdir(dir_of_month) unless FileTest.directory?(dir_of_month)
    
    i = n_photo_dir(dir_of_month)
    count = 0
    
    @H.each do |d, ls_files|    #dはディレクトリ
      i += 1
      d_to = File.join(dir_of_month, sprintf("photo%02d", i))
      Dir.mkdir(d_to)
      
      ls_files.each do |f|
        f_from = File.join(d, f)
        f_to = File.join(d_to, f)
        FileUtils.cp(f_from, f_to)
         
        unless FileUtils.cmp(f_from, f_to)
          puts "Copy failed: #{f_from} => #{f_to}"
          abort
        end
        File.delete(f_from)
        count += 1
        puts "#{count}/#{total_files}"
      end
    end
  end
end

HD    = '/home/pub/photos/'
MEDIA = '/media/usbdisk/'

Photo.new.move_photos(MEDIA, HD)