multi_rename.rb

#一括リネーマ
=begin
「変換するファイル    変換後ファイル名」
の入力行($stdin)を解釈して一括リネームする。
paste コマンドで作れるフォーマットなので。

依存・制限
・FileUtilsライブラリ
・Shellwordsライブフリ
・現在Winのロングパス非対応
=end
  
  require 'shellwords'
  require 'fileutils'
  include FileUtils
  class RejectionError < RuntimeError ; end
  class NoFileError < RuntimeError ; end
  class FormatError < RuntimeError ; end
  OLD = 0
  NEW = 1
  
begin
  names = Array.new   #変換予定テーブル
  
  
  while line = STDIN.gets
    name = Shellwords.shellwords(line.strip)
    next if name.length == 0
    raise(FormatError, "入力が不正です") unless name.length == 2
    
    #変換予定を表示
    STDERR.puts "#{name[OLD]} -> #{name[NEW]}"
    
    #元ファイルの存在をチェック
    unless File.exist?(name[OLD])
      raise(NoFileError, "#{name[OLD]}: そのようなファイルやフォルダは存在しません")
    end
    
    #リネーム後の上書きチェック
    if File.exist?(name[NEW])
      buf = String.new
      STDERR.print "#{name[NEW]} は既に存在します。上書きしますか? (Y/N) ->"
      STDERR.print "->" until /^[yn]$/i =~ ( buf = STDIN.gets.chomp )
      raise(RejectionError, "#{name[NEW]} の上書きを拒否しました") if /^n$/i =~ buf
      
    end
    
    names << name   #変換予定を配列に保持
  end
  
  
rescue RejectionError => exception
  STDERR.puts exception.message
  retry
    
rescue NoFileError => exception
  STDERR.puts exception.message
  retry
    
rescue FormatError => exception
  STDERR.puts "#{exception.class}: #{exception.message}"
  retry
  
rescue => exception
  STDERR.puts "#{exception.class}: #{exception.message}"
  exit(1)
  
end


#処理開始
  names.each do |name|
    FileUtils.mv(name[OLD], name[NEW])
  end
    
#事後報告
  STDERR.puts "#{names.length} 個のファイルをリネームしました"