I’ve recently developed a tool that helps in keeping your music library clean and organized.
It allows you to rename and reorganize all your music library in batch using your mp3 tags.
Of course the tool works best only if your mp3 files have tags complete with all the details such as artist, album, year, track number…
The script is based on the mp3info gem; this gem can read information and manipulate mp3 tags.
My tool examines all mp3 files contained into base_source_dir
folder, it moves them into the base_target_dir
folder organizing them following the user defined structure according to dir
method and rename files according to filename
method. Here’s the code:
#!/usr/bin/env ruby
require 'rubygems'
require 'mp3info'
require 'titleize'
require 'fileutils'
require 'ruby-progressbar'
def base_source_dir
'/Volumes/Shared/Music/Tmp'
end
def base_target_dir
'/Volumes/Shared/Music/Temporary'
end
def invalid_character
Regexp.new('[|/\\<>:"?*;,^]')
end
class Mp3
attr_accessor :source_path, :artist, :album, :title, :year, :track_n, :disc_n
def initialize(path)
@source_path = path
get_metadata
end
def self.all
Dir.glob("#{base_source_dir}/**/*.mp3").map do |path|
new(path)
end
end
def filename
"#{escape(artist)} - [#{year}] #{escape(album)} - #{leading_0(disc_n)}.#{leading_0(track_n)} - #{escape(title)}.mp3"
end
def dir
"#{escape(artist)}/[#{year}] #{escape(album)}"
end
def target_dir
"#{base_target_dir}/#{dir}"
end
def target_path
"#{target_dir}/#{filename}"
end
private
def get_metadata
Mp3Info.open(source_path) do |mp3info|
@artist = mp3info.tag.artist
@album = mp3info.tag.album.titleize
@title = mp3info.tag.title.titleize
@year = mp3info.tag.year || mp3info.tag1.year || mp3info.tag2.TDRC
@track_n = mp3info.tag.tracknum || 1
@disc_n = mp3info.tag2.disc_number || 1
end
end
def escape(tag)
tag.gsub(invalid_character, '_')
end
def leading_0(tag)
sprintf '%02d', tag
end
end
class Mp3Renamer
attr_accessor :source_path, :target_path, :target_dir
def initialize(mp3)
@source_path = mp3.source_path
@target_dir = mp3.target_dir
@target_path = mp3.target_path
end
def perform
prepare_folder
FileUtils.mv(source_path, target_path)
end
private
def prepare_folder
FileUtils.mkdir_p target_dir
end
end
mp3s = Mp3.all
bar = ProgressBar.create total: mp3s.count
FileUtils.mkdir_p base_target_dir
mp3s.each do |mp3|
Mp3Renamer.new(mp3).perform
bar.increment
end
puts "#{mp3s.count} mp3 processed!"
Here’s my organization method, enjoy your listening!
Leave a Reply