MP3 ファイルのタグ付けを一気にやるrubyスクリプト改
ここを見てついむらむらっときて、以前作ったスクリプト書き直した。
コメントにも書いてありますが実行するとカレントディレクトリ以下の mp3 ファイルを操作して自動的にタグ付けを行います。詳細はスクリプトのコメント参照のこと。
もっと便利にして exe 化したらみんな喜ぶのかしら。
あ、使う前に
gem install mp3info
する必要があります。
(2009/07/01 追記: 動作確認は Windows で行いました)
#!/bin/env ruby # # MP3 ファイルのタグ付けを一気にやるrubyスクリプト改 # # 名前の通り mp3 ファイルのタグ付けを行います。実行すると、 # カレントディレクトリ以下を操作して全ての mp3 ファイルのタグ付けを # ディレクトリ構造に従って行います。 # # 設定は Settings::Configuration に対して行います。この定数は Hash です。 # キー名がディレクトリ名を示し、ディレクトリ単位に設定をすることができます。 # :__default__ キーはデフォルトの設定です。 # # 今のところ設定できる項目は :artist キーだけです。これはアーティスト名の # 指定で、カレントディレクトリから何階層名をアーティスト名として扱うか # 設定します。デフォルトは1です。つまりカレントディレクトリ直下の # ディレクトリ名がアーティスト名として利用されます。 # # アルバム名は mp3 ファイルの直上のディレクトリ名です。タイトルは mp3 ファイルの # ファイル名から .mp3 を除いたものが設定されます。 # require 'rubygems' require 'mp3info' require 'pathname' module Settings Configuration = { :__default__ => { :artist => 1 } } end class Mp3Tagger def initialize(path, artist) @path = path @artist = artist @album = File.basename(File.expand_path(path.parent.to_s)) @title = File.basename(path.to_s)[0..-5] end def need_update?(name) @original[name.to_sym] != instance_variable_get("@#{name}".to_sym) end def update_tag(name) new_name= instance_variable_get("@#{name}".to_sym) @mp3.tag.__send__((name.to_s << '=').to_sym, new_name) @changed ||= {} @changed[name] = new_name end def putchanges(*keys) keys.each do |key| puts " #{key}: #{@original[key]} => #{@changed[key]}" if @changed.has_key?(key) end end def update_tags_if_need(*tag_names) tag_names.each do |tag_name| update_tag(tag_name) if need_update?(tag_name) end end def update begin update_tags_if_need :artist, :album, :title ensure @mp3.close if @changed end if @changed puts @path putchanges :artist, :album, :title end end def execute @mp3 = Mp3Info.open @path.realpath.to_s @original = {:title => @mp3.tag.title, :artist => @mp3.tag.artist, :album => @mp3.tag.album} update end end class TagHandler include Settings def initialize(path='./') @path = path @setting = Configuration[:__default__] end private def record yield read_last_run end public def process(path, relpath_str='', depth=1) path = Pathname.new path Dir.open(path).each do |relpath_str| next if relpath_str == '.' || relpath_str == '..' relpath = Pathname.new relpath_str if File.directory?(path+relpath) if depth == 1 if Configuration.include? relpath_str @setting = Configuration[relpath_str] else @setting = Configuration[:__default__] end @artist = nil end @artist = relpath_str if depth == @setting[:artist] process(path+relpath, relpath_str, (depth+1)) else next if File.extname(relpath_str) != '.mp3' begin tagger = Mp3Tagger.new(path+relpath, @artist) tagger.execute rescue Mp3InfoError => e @errors ||= [] error = { :file => path+relpath, :message => e.message } @errors << error end end end end def tagging process @path end attr_reader :errors end handler = TagHandler.new handler.tagging if handler.errors puts puts "Error occured" handler.errors.each do |error| puts " #{error[:file]}" puts " #{error[:message]}" end end print "\nPlease hit Enter for exit." $stdin.gets exit