This is a quick script I whipped up to collapse some folder trees down to individual folders. The specific situation that arose was my formerly-itunes collection (it's currently organized Music\artist\album\songs.(mp3|m4a) and I'd really prefer it to be Music\artist\song.(mp3|m4a)).
#!/usr/bin/ruby
require 'optparse'
require 'pp'
require 'fileutils'
### parsing command line options via optparse, nothing to see here
options={}
optparse = OptionParser.new do|opts|
opts.on('-h', '--help',
'Display this screen') do
puts opts
exit
end
opts.on('-t', '--type a,b,c',
Array, 'Specify filetypes to flatten out (defaults to mp3,m4a)') do|t|
options[:types] = t
end
end
optparse.parse!
### the setup (ideally, this would be in a `let` statement)
origin = Dir.pwd
if not options[:types]
options[:types] = ["mp3", "m4a"]
end
### the actual work
ARGV.each do |target|
FileUtils.cd("#{origin}/#{target}")
options[:types].each{|ext| `find -iname '*.#{ext}' -exec mv {} ./ \\\;`}
`find -depth -type d -empty -exec rmdir {} \\\;`
end
FileUtils.cd(origin)
Am I doing anything eye-stabbingly wrong? Is there a better way of handling any of the above?
Specifically, I suspect that I could replace the find calls with native Ruby methods, but I can't see how without complicating it significantly. I also suspect that there's a better way of writing FileUtils.cd("#{origin}/#{target}"), but a cursory reading of Dir doesn't reveal anything. Any tips?
#!/usr/bin/ruby
require 'optparse'
require 'pp'
require 'fileutils'
### parsing command line options via optparse
options={:types => ["mp3", "m4a"]}
optparse = OptionParser.new do|opts|
opts.on('-h', '--help', 'Display this screen') do
puts opts
exit
end
opts.on('-t', '--type a,b,c', Array, 'Specify filetypes to flatten out (comma separated, defaults to mp3,m4a)') do|t|
options[:types] = t
end
end
optparse.parse!
### the actual work
ARGV.each do |target|
FileUtils.cd(target) do
options[:types].each{|ext| `find -iname '*.#{ext}' -exec mv {} ./ \\\;`} ##move all matched files into [target]
`find -depth -type d -empty -exec rmdir {} \\\;` ##recursively delete all empty folders in [target]
end
end
optionsis now initialized beforehand rather than being checked after.parse!- using the block option on
FileUtils.cd - removed useless final
cdback - tried the
globoption, but it just errors without continuing if it hits a matched file intarget(ie. one that needs to stay where it is). This seems to happen when I pass:force => TRUEtoo. Thefindcall notes such files, but still flattens what it can. Theglobroute also doesn't seem to be case-insensitive.