Sometimes, I need to rename many files in a systematic way (either strip off some part of the filename or replace it with another string).
Although you can solve that problem using a shell scripting language and sed there is a lot of potential to mistype the sed command
resulting in data loss.
An obvious choice would have been to use perl, but I decided to give it a try with ruby.
Here is the result, may this can serve as a simple example (and hopefully not a good example of a bad example :) )
#!/usr/bin/ruby # Project: rename files # Date: Thu Sep 21 13:02:57 CEST 2006 # Author: Nicholas Stallard # Description: change parts of a filename to something else # get the command line parameters require 'getoptlong' # this is for the cvs cvsversion = "$Revision: 1.9 $" version = cvsversion.split.slice(1) # program information progname = File.basename($0,".rb") proginfo = progname+" "+version # parameter defaults dofiles = FALSE from = "" to = "" # get the options opts = GetoptLong.new( [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--onlyfiles", "-o", GetoptLong::NO_ARGUMENT ], [ "--from", "-f", GetoptLong::REQUIRED_ARGUMENT ], [ "--to", "-t", GetoptLong::REQUIRED_ARGUMENT ], [ "--uppercase", "-u", GetoptLong::REQUIRED_ARGUMENT ], [ "--lowercase", "-l", GetoptLong::REQUIRED_ARGUMENT ], [ "--capitalize", "-c", GetoptLong::REQUIRED_ARGUMENT ], [ "--remove", "-r", GetoptLong::REQUIRED_ARGUMENT ] ) # clean exit upon control-c trap("INT") { exit 1 } # show some help def printusage (info, name) puts info puts puts "Usage:" puts puts name+" [--onlyfiles] --from=<string> --to=<replacement string>" puts puts "Shortcuts:" puts " --uppercase=<string>" puts " --lowercase=<string>" puts " --captialize=<string>" puts " --remove=<string>" puts puts "The string transformation is applied to all items in the current directory" puts "unless the option --onlyfiles is supplied, where only file names are manipulated" puts end # if no argument was supplied, also display help :-) if (ARGV.empty?) printusage(proginfo, progname) exit end # get the arguments opts.each do |opt, arg| case opt when '--help' printusage(proginfo, progname) exit when '--from' from = arg when '--to' to = arg when '--uppercase' from = arg to = from.upcase when '--lowercase' from = arg to = from.downcase when '--remove' from = arg to = "" when '--capitalize' from = arg to = from.capitalize when '--onlyfiles' dofiles = TRUE end end # there is a bug, some say it may be a feature :-) # supplying --from without --to works like --remove # set up an array containing all the items in the current directory # matching the regular expression filelist = Dir.glob("*") # only rename files, omit directories if dofiles newfiles = Array.new filelist.each do |d| if File.file?(d) newfiles.push(d) end end filelist = newfiles end # And process each element within the array filelist.each do |d| # replace one string with another nfn = d.gsub(/#{from}/, "#{to}") # this will empty a string if it is full of whitespaces nfn.strip! # avoid mayhem and disallow empty names if (nfn.empty?) puts "Error: Resulting name would be empty!" exit 1 end # No need to rename if old and new name are identical if ( d == nfn ) puts "Warning: Not renaming "+d+" (New name is identical to old one)" next end # do not overwrite existing items if ( File.file?(nfn) ) puts "Error: Cowardly refusing to rename "+d+" ("+nfn+" exists!)" next end # and proceed with the rename operation File.rename(d, nfn) puts "Renamed "+d+" to "+nfn end exit 0