*update* I added the music sort files to a github repo: http://github.com/victusfate/music-sort
I've got a fairly sizable collection of music. It's more than I need, and certainly more than I want to worry about. I decided before nuking it to make one more effort to clean it up and shrink it down to one directory. This script could have been 21 lines of code but I preferred monitoring it with a puts statement.
The first pass code:
require 'fileutils'
orig = '/home/messel/Desktop/music/'
dest = '/home/messel/Desktop/mobilemusic/'
Dir.chdir(orig)
Dir.glob('*.m3u') do |m3u_name|
m3us = IO.readlines(m3u_name)
out_m3u = File.new(dest+m3u_name,'w+')
m3us.each do |m3u|
m3u.gsub!(/\/,'/')
b1 = File.basename(m3u)
out_m3u << b1 # write new m3u with carriage return
m3u = m3u.chomp # remove carriage return for file manip
unless m3u['#']
basename = File.basename(m3u)
puts "orig #{orig+m3u} dest #{dest+basename}"
if File.exist? orig+m3u and !File.exist? dest+basename
FileUtils.cp(orig+m3u,dest+basename)
end
end
end
out_m3u.close
end
As you can imagine for large music collection operations, there were a number of exception files that were missing or had special characters I failed to handle. My next script identified the missing files from my new music collection folder, but that were still referenced on playlists.
def check_for_file(m3u_name)
m3us = IO.readlines(m3u_name)
m3us.each do |m3u|
m3u = m3u.chomp # remove carriage return for file manip
puts "List #{m3u_name} missing #{m3u}" unless File.exist? m3u or m3u['#']
end
end
if (ARGV.size > 0)
check_for_file ARGV[0].to_s
else
Dir.glob('*.m3u').each do |m3u_name|
check_for_file m3u_name
end
end
For this script I added an optional parameter (ARGV) to let me test it on a single file first before going hog wild in the full directory. After identifying a number of missed files, I modified the missing script to go back and grab the files from another remote disk where I back up much of my older music.
require 'fileutils'
def check_for_file(m3u_name,path,opath)
m3us = IO.readlines(m3u_name)
m3us.each do |m3u|
m3u = m3u.chomp # remove carriage return for file manip
unless File.exist? m3u or m3u['#']
puts m3u
Dir.glob(path+'**/'+m3u).each do |found|
puts "found file on FIRELITE #{found}"
FileUtils.cp(found,opath + m3u)
# Process.exit
end
end
end
end
path = '/media/FIRELITE_/music/'
opath = '/home/messel/Desktop/music/'
if (ARGV.size > 0)
check_for_file ARGV[0].to_s, path, opath
else
Dir.glob('*.m3u').each do |m3u_name|
check_for_file m3u_name, path, opath
end
end
Even after all that there were many play lists with files that I no longer had or knew their whereabouts. Thus came the great pruning. The following program identifies at least one missing music file, then creates a new output play list skipping over any missing files.
require 'fileutils'
def check_for_file(m3u_name,opath)
prune = false
m3us = IO.readlines(m3u_name)
m3us.each do |m3u|
m3u = m3u.chomp # remove carriage return for file manip
unless File.exist? m3u or m3u['#']
prune = true
break
end
end
if prune
puts "Pruning from #{m3u_name}"
FileUtils.mv(m3u_name,opath+"back_"+File.basename(m3u_name))
out_m3u = File.new(opath+File.basename(m3u_name),'w+')
prevline = ''
m3us.each do |m3u_line|
m3u = m3u_line.chomp # remove carriage return for file manip
if m3u['#']
prevline = m3u + "\n"
next
end
if File.exist? m3u
# puts prevline unless prevline.length == 0
# puts m3u_line
out_m3u << prevline unless prevline.length == 0
out_m3u << m3u_line
prevline = ''
end
end
out_m3u.close
end
end
opath = '/home/messel/Desktop/music/'
if (ARGV.size > 0)
check_for_file ARGV[0].to_s, opath
else
Dir.glob('*.m3u').each do |m3u_name|
check_for_file m3u_name, opath
end
end
But I wasn't very careful with my script, and used '\n' instead of "\n" (corrected above) which mean instead of line feeds (carriage returns for ancient typewriter folks like me) between description and file lines, I had ONE BIG MESS. After rolling my sleeves up and spelunking the dangerous caverns of regular expressions I came up with one final script to correct my woes. This script was appropriately labeled "oh_god_why.rb".
require 'fileutils'
def check_for_file(m3u_name,opath)
prune = false
m3us = IO.readlines(m3u_name)
out_m3u = File.new(opath+File.basename(m3u_name),'w+')
m3us.each do |m3u_line|
out_m3u << m3u_line.gsub(/\n/,"\n")
end
out_m3u.close
end
opath = '/home/messel/Desktop/music/'
if (ARGV.size > 0)
check_for_file ARGV[0].to_s, opath
else
Dir.glob('*.m3u').each do |m3u_name|
check_for_file m3u_name, opath
end
end
Astute readers will notice that I've included several programs beyond the original 22 line script throughout this post. When it comes to doing jobs right, I believe a slight exaggeration goes a long way, but it's best to show your friends the full truth. "Pay no attention to the man behind the curtain".
references: