MP3 の ID3 タグをいじってみようとするがうまくいかず

MP3*1 には、アーティストや曲名の情報を記述するための
ID3 タグという規格がある。
僕の音楽ディレクトリの中にある MP3 ファイルの名前を、
「アーティスト - 曲名.mp3」に統一したいなぁと前から思っていたので、
今回それを Ruby でやってみることにした。


とりあえず ID3 タグをいじれるっぽいライブラリをインストールする。

> gem install id3lib-ruby

なんかいくつかバージョンがあるらしく選択項目が出てきたので、
一番バージョンの新しい mswin32 用のを選択した。


http://id3lib-ruby.rubyforge.org/ を見た感じでは、

filename = "世界に一つだけの花.mp3"
tag = ID3Lib::Tag.new(filename)

tag.title #=> "世界に一つだけの花" 

って感じで使えるらしい。


早速簡単なスクリプトを書いて実行してみる。
が、うまくいかない・・・。


とりあえず今できているのは、
ディレクトリのパスを指定して、
それ以下に含まれる MP3 ファイルの一覧を出力するところまで。
覚えたての Find モジュールも使ってみた。
Find モジュールを使うとディレクトリの再帰処理が楽チン。

require "find"
require "rubygems"
require "id3lib"

# IGNORES の要素は読み飛ばすディレクトリのパス
IGNORES = [/\./, /\.\./]

def list_title(topdir)
  Find.find(topdir){|path|
    if FileTest.directory?(path)
      dir, base = File.split(path)
      IGNORES.each{|re|
        # re に base がマッチする場合 path を読み飛ばす
        Find.prune if re =~ base
      }
    else
      if /\.mp3$/ =~ path
        filename = File.basename(path)
        # ファイル名の先頭にある余計な数字を除去
        filename.sub!(/^\d+[- ]/, '')
        
        ## tag が nil なのがおかしい
        # tag = ID3Lib::Tag.new(filename)
        # puts tag.title #=> nil
        
        puts filename
      end
    end
  }
end

topdir = "E:/音楽/"
list_title(topdir)

なんで tag が nil になっちゃうんだろう?
これさえ何とかなれば大丈夫だと思うんだけどなぁ。

追記

うまくいった!
問題はID3Lib::Tag.new()の引数にファイル名を与えていたことだった。
パスを与えないとダメみたい。
考えてみればすごい当たり前のことだった。
他にも余分なコードとかあったので削って書き直した。
以下が修正後のコード。

# list-id3tag.rb
#
# 指定したパス以下に含まれるMP3のID3タグを読み取り、
# その一覧を出力する。
#
# usage: ruby list_id3tag.rb [topdir]

require "find"
require "rubygems"
require "id3lib"

# IGNORES の要素は読み飛ばすディレクトリのパス
IGNORES = [/\./, /\.\./]

def list_id3tag(topdir)
  Find.find(topdir){|path|
    if FileTest.directory?(path)
      dir, base = File.split(path)
      IGNORES.each{|re|
        # re に base がマッチする場合 path を読み飛ばす
        Find.prune if re =~ base
      }
    else
      if /\.mp3$/ =~ path
        tag = ID3Lib::Tag.new(path)
        puts tag.title
        puts tag.artist
        puts tag.album
        puts tag.track
        puts tag.year
        puts tag.genre
        puts
      end
    end
  }
end

topdir = ARGV[0] || "E:/音楽/"
list_id3tag(topdir)


出力結果の例はこんな感じ。
これで一曲分。
こんなのがドドドーっと一覧になって出力される。

この道わが旅(II)
すぎやまこういち
SYMPHONIC SUITE 「DRAGONQUEST」 BEST SELECTION〜ROTO〜
8
1997
Game

あれ?そういえば当初の目的はまだ達成されてないような・・・。

*1:大文字で書くのが正しいらしい