Sunday, September 5, 2010

for anything complicated, ruby eats bash for breakfast

http://www.sklav.com/node/4 shows a bash solution to the issue debated here. Regardless of how good a bash script is, it inevitably is not very DRY, I think because it is hard to be DRY in bash scripting.

Here is a ruby solution. Of course, all I did was factor, which is easy in ruby:


#!/usr/bin/env ruby

lame_opts = "--preset standard -q0"

if ARGV.size == 0
  puts "usage: #{File.basename(__FILE__)} .flac ..."
  puts "output: .mp3"
  puts ""
  puts "uses lame opts: #{lame_opts}"
  puts "retains tag info"
  exit
end

tag_convert = {
  :tt => "TITLE",
  :tl => "ALBUM",
  :ta => "ARTIST",
  :tn => "TRACKNUMBER",
  :tg => "GENRE",
  :ty => "DATE",
}

ARGV.each do |file|
  tag_opts = tag_convert.map do |key,val|
    # comes out as TITLE=
    data = `metaflac --show-tag=#{val} #{file}`.split("=",2).last
    "--#{key} #{data}"
  end
  mp3name = file.chomp(File.extname(file)) + ".mp3"
  `flac -dc #{file} | lame #{lame_opts} #{tag_opts.join(" ")} --add-id3v2 - #{mp3name}`
end
Fairly easy to follow, especially since we don't repeat ourselves. Most of the code is in creating a useful help message.

For Perl hackers, here is the entire script on a few lines of less than 105 chars per line:

tag_convert = {:tt=>"TITLE",:tl=>"ALBUM",:ta=>"ARTIST",:tn=>"TRACKNUMBER",:tg=>"GENRE",:ty=>"DATE"}
ARGV.each do |f| 
  tgs = tag_convert.map {|k,v| "--#{k} "+`metaflac --show-tag=#{v} #{f}`.split("=",2).last}.join(" ")
  `flac -dc #{f} | lame --preset standard -q0 #{tgs} --add-id3v2 - #{f.sub(/.flac$/i,".mp3")}`
end
There are still ways to compress this further, but it is very concise and surprisingly easy to follow (if you know ruby).

No comments: