122 lines
2.6 KiB
Ruby
Executable File
122 lines
2.6 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
||
|
||
require "io/console"
|
||
require "optparse"
|
||
|
||
=begin
|
||
Limits:
|
||
- ~ not properly managed
|
||
- \ and / chars may be a problem
|
||
|
||
Dependencies: vorbis-tools, mid3v2
|
||
=end
|
||
|
||
CTRL_C = "\u0003"
|
||
|
||
options = {
|
||
music_ext: "mp3,ogg",
|
||
library: "#{ENV['HOME']}/Music",
|
||
yes: false,
|
||
dry: false,
|
||
}
|
||
|
||
opt_parse = OptionParser.new do |opts|
|
||
opts.banner = "Usage: id3bulk [options] [directories]"
|
||
|
||
opts.on("-l=PATH", "--library=PATH", "Library to edit music in. Default ~/Music.") do |dir|
|
||
options[:library] = dir
|
||
end
|
||
|
||
opts.on("-y", "--yes", "No confirm. Default ask keyboard confirmation.") do
|
||
options[:yes] = true
|
||
end
|
||
|
||
opts.on("-d", "--dry-run", "Do not modify files, only show up.") do
|
||
options[:dry] = true
|
||
end
|
||
end
|
||
opt_parse.parse!
|
||
|
||
if ARGV.empty?
|
||
puts opt_parse
|
||
exit 1
|
||
end
|
||
|
||
if options[:library] != ""
|
||
options[:library].gsub!(/^~/, ENV["HOME"])
|
||
Dir.chdir options[:library]
|
||
end
|
||
|
||
def execute(cmd, options)
|
||
if !options[:dry]
|
||
system(cmd)
|
||
else
|
||
cmd
|
||
end
|
||
end
|
||
|
||
class String
|
||
def songify!(artist: "")
|
||
# handle special chars
|
||
tr!(' ', ' ')
|
||
|
||
# handle special suffix
|
||
gsub!(/ \[[\w_-]{11}\]$/, '')
|
||
gsub!(/ \([\w_-]{11}\)$/, '')
|
||
gsub!(/-[\w_-]{11}$/, '')
|
||
gsub!(/[||_-] *Napalm Records/i, '')
|
||
gsub!(/\((Official Lyric Video|Official Video|Official)\)/i, '')
|
||
gsub!(/Lyrics|\(Lyrics\)$/i, '')
|
||
|
||
# handle prefix
|
||
gsub!(/^#{artist}/i, '')
|
||
|
||
# handle lost spaces and special chars
|
||
gsub!(/^[ _-]*/, '') # leading chars
|
||
gsub!(/[\s]+/, ' ') # multiple spaces
|
||
end
|
||
end
|
||
|
||
ARGV.each do |dir|
|
||
Dir["#{dir}/**/*.{#{options[:music_ext]}}"].each do |filepath|
|
||
artist, *subdirs, music = filepath.split("/")
|
||
|
||
subdirs.filter! { _1 != "" }
|
||
artist.tr!('"', "'")
|
||
|
||
song = music.gsub(/\.(#{options[:music_ext].tr(',', '|')})$/, '')
|
||
song.songify!(artist:)
|
||
|
||
album = subdirs.last || artist
|
||
|
||
cmd =
|
||
if filepath =~ /\.mp3/
|
||
"mid3v2 --album \"#{album}\" --artist \"#{artist}\" --song \"#{song}\" \"#{filepath}\""
|
||
elsif filepath =~ /\.ogg/
|
||
"vorbiscomment -w --tag album=\"#{album}\" --tag artist=\"#{artist}\" --tag song=\"#{song}\" \"#{filepath}\""
|
||
else
|
||
puts "Can't handle \"#{filepath}\""
|
||
next
|
||
end
|
||
|
||
if options[:yes] == true
|
||
puts cmd
|
||
execute(cmd, options)
|
||
else
|
||
puts cmd
|
||
print "Confirm? (y/N/e) "
|
||
char = STDIN.getch
|
||
print char
|
||
if char == "e" || char == CTRL_C
|
||
exit 0
|
||
elsif char == "y"
|
||
puts `\n#{execute(cmd, options)}`
|
||
else
|
||
puts "\npass"
|
||
end
|
||
end
|
||
|
||
puts
|
||
end
|
||
end
|