音楽ファイルを必要なものだけフィルタしてコピーする

僕の iTunes ライブラリには10年以上ためこんだ音楽が入っているが、例えばカラオケトラックやドラマCDなどは普段聴かないので除外している。

iTunes ではこれをスマートプレイリストで実現しているが、今回はこれをファイルベースでやる必要が出てきた(聴くものだけSDカードにコピーしたかった)ので、Ruby でサクッとスクリプトを書いてみた。

copy_musics のブロックで条件付けを後からいろいろ変更できるようにしたつもり。

Gemfile

source :rubygems

gem "taglib-ruby", "~> 0.7.1"

スクリプト

require 'taglib'
require 'find'
require 'fileutils'

def is_file_equal?(source, destination)
  if !File.exist?(destination)
    return false
  end
  if FileTest.size(source) != FileTest.size(destination)
    return false
  end
  if File.mtime(source) < File.mtime(destination)
    return false
  end
  return true
end

def copy_musics(input_dir, destination_dir)
  Find.find(input_dir) do |source_path|
    target_path = destination_dir + source_path.slice(input_dir.length, source_path.length)
    if FileTest.directory?(target_path)
      next
    end
    if is_file_equal?(source_path, target_path)
      next
    end
    if FileTest.zero?(source_path)
      next
    end
    check = false
    TagLib::FileRef.open(source_path) do |fileref|
      unless fileref.null?
        check = yield(fileref.tag, source_path)
      end
    end
    if !check
      next
    end

    puts target_path
    target_dir = File.dirname(target_path)
    if !Dir.exist?(target_dir)
      FileUtils.mkdir_p(target_dir)
    end
    FileUtils.cp(source_path, target_path)
  end
end

input_dir = ARGV[0]
destination_dir = ARGV[1]

copy_musics(input_dir, destination_dir) do |music|
  album  = music.album
  title  = music.title
  artist = music.artist
  genre = music.genre

  # カラオケ
  next false if title =~ /off vocal/i ||
                title =~ /vocal off/i ||
                title =~ /karaoke/i ||
                title =~ /カラオケ/i ||
                title =~ /からおけ/i ||
                title =~ /without/i ||
                title =~ /いないver\./i || # ひぐらしのCDにあった
                title =~ /[\(-]inst/i ||
                title =~ /Instrumental/i

  # ドラマCD
  next false if album =~ /ドラマCD/ ||
                album =~ /サウンドステージ/ ||
                album =~ /サウンドブック/


  # アイマスのドラマパート・サントラ
  next false if album =~ /IDOLM@STER/i && (
                title =~ /トーク ?\d\d/ ||
                title =~ /トラック ?\d\d/ ||
                title =~ /SCENE ?\d\d/ ||
                title =~ /ボーナス・トラック/ ||
                title =~ /^ドラマ/ ||
                title =~ /^DRAMA/i ||
                album =~ /IDOLM@STER STATION/i ||
                album =~ /THE IDOLM@STER ANIM@TION MASTER/i
  )

  # サウンドトラックを除外 ただし "Princess Piccolo" Original Soundtrack -2nd Edition- は残す
  next false if (
                 album =~ /サウンドトラック/ || 
                 album =~ /サントラ/ || 
                 album =~ /soundtrack/i ||
                 album =~ /sound track/i ||
                 album =~ /O\.S\.T/i
                ) && (album !~ /Princess Piccolo/)

  # そもそもアルバム名が入ってない
  next false if album == ""

  true
end

つかいかた

$ bundle exec ruby musicsync.rb ~/Music/iTunes/iTunes\ Music/Music /Volumes/Musics/Musics