Class | RecursiveUtils::Rename |
In: |
recursiveutils.rb
|
Parent: | Object |
再帰処理機能, 文字コード変換機能を実装した Ruby 版 rename.
require 'recursiveutils' obj = RecursiveUtils::Rename.new obj.gsub('f..', 'bar', 'foo.txt') # => 対象ファイルの /f../ を "bar" に変換する obj.recursive = true obj.upcase('/usr/local/src/') # => 対象ディレクトリ以下のファイルを全て大文字に変換 obj.recursive = false obj.name_type = 'e' obj.downcase('FOO.TXT', 'BAR.JPG') # => 対象ファイルの拡張子を小文字に変換 obj.name_type = nil obj.convert('euc', Dir.glob('./*.txt')) # => 対象ファイルの文字コードを euc に変換 obj.rename(Dir.glob('./*.txt')){ |i| i.swapcase.gsub('X', '_') } # => 対象ファイルの大文字と小文字を変換後, "X" を "_" に置換
初期化: | new |
ファイル操作: | rename, gsub, upcase, downcase, convert |
設定: | figure=, number= |
確認: | confirm |
rename.rb: | www.ep.sci.hokudai.ac.jp/~daktu32/DOC/ruby/works/ruby_works.htm |
escape | [RW] | 変換パターンの正規表現のメタ文字を保護する. |
figure | [R] | 設定された桁数の連番に置換する. |
force | [RW] | 確認無しで処理を実行する. |
name_type | [RW] | 処理対象を限定する. 先頭の文字が b (basename), e (extname) の時のみ有効. |
noop | [RW] | 変換処理を行わない. |
number | [R] | 連番の初期値. デフォルトは 1. |
quiet | [RW] | メッセージを抑制する. |
新規オブジェクトを作成する. オプションの意味は FullPathList::Flag と Rename の Attributes を参照する事.
# File recursiveutils.rb, line 389 def initialize(opts = {}) set_flag(opts) @noop = opts[:noop] @force = opts[:force] @name_type = opts[:name_type] @escape = opts[:escape] @quiet = opts[:quiet] self.figure = opts[:figure] || 0 self.number = opts[:number] || 1 end
path 中のファイル名の文字コードを code に変換する.
# File recursiveutils.rb, line 545 def convert(code = LOCALE_NAME, *path) unless txt = LocaleFilter.japanese_code?(code) raise ArgumentError, "#{code}: Invalide character code." end lf = LocaleFilter.new(txt, nil, @file_code) message = %Q{ (Convert to "#{txt}")} puts %Q(Convert filename encode to "#{txt}".) unless @quiet rename(path, message){ |i| lf.tolocale(i) } end
path 中のファイル名を小文字に変換する.
# File recursiveutils.rb, line 540 def downcase(*path) rename(path){ |i| i.downcase } end
@figure の設定用メソッド. num が 負の場合は例外 ArgumentError を返す.
# File recursiveutils.rb, line 402 def figure=(num) num = Integer(num) raise ArgumentError, "#{num}: Invalid size." if num < 0 @figure = num end
path 中の正規表現 from に一致するファイル名を to に変換する.
# File recursiveutils.rb, line 503 def gsub(from, to, *path) p "from: #{from}, to: #{to}" if @debug lf = LocaleFilter.new input = lf.japanese_code?(@input_code) if to_code = (input || lf.japanese?(to) || lf.japanese?(from)) lf.input = input from = lf.toeuc(from) to = lf.toeuc(to) code = 'e' else to = to.to_s end opt = Regexp::IGNORECASE if @casefold from = Regexp.escape(from, code) if @escape from = Regexp.new(from, opt, code) p "from: #{from}, to: #{to}, to_code: #{to_code}" if @debug if to_code ff = LocaleFilter.new('euc', nil, @file_code) lf.locale = to_code lf.input = 'euc' rename(path){ |i| lf.tolocale(ff.tolocale(i).gsub(from, to)) } else rename(path){ |i| i.gsub(from, to) } end end
@number の設定用メソッド. num が 負の場合は例外 ArgumentError を返す.
# File recursiveutils.rb, line 410 def number=(num) num = Integer(num) raise ArgumentError, "#{num}: Invalid size." if num < 0 @number = num end
配列 list を元に作成した処理対象をブロックで変換する.
# File recursiveutils.rb, line 417 def rename(list, message = nil) # :yields: target raise LocalJumpError, 'Error: No block given.' unless block_given? path_list = FullPathList.get(flag2hash, list) if path_list.empty? warn 'No files will be converted.' unless @quiet return false end src_list = Hash.new{ |h, k| h[k] = Array.new } new_list = src_list.dup type = @name_type.to_s[0, 1].downcase figure = @figure if @figure > 0 path_list.each do |path| dir, before = File.split(path) case type when 'b' after = yield(File.basename(before, ".*")) << File.extname(before) when 'e' after = File.basename(before, ".*") << yield(File.extname(before)) else after = yield(before) end if figure number = sprintf("%0*d", figure, src_list[dir].size + @number) after = after.gsub('/', number) end if before != after src_list[dir] << before new_list[dir] << after end end if new_list.empty? warn 'No files will be converted into such a pattern.' unless @quiet return false end src_list = src_list.sort_by{ |k, v| k } unless @quiet lf = LocaleFilter.new src_list.each do |k, v| next unless new_list[k] puts "\n#{k}:" max = v.map{ |i| lf.tolocale(i).size }.max v.each_index do |i| print ' ', lf.tolocale(v[i]).ljust(max) puts message || " => #{new_list[k][i]}" end end puts end return true if @noop unless @force stderr new_list.values.flatten.size, ' files' stderr " (in #{new_list.size} directories)" if new_list.size > 1 stderr ' will be renamed. ' confirm('Do you sure rename') or return false end src_list.each do |k, v| next unless new_list[k] v.each_index do |i| src_path = File.join(k, v[i]) new_path = File.join(k, new_list[k][i]) if ! @force && test(?e, new_path) warn %Q("#{new_path}" is already exist. ) confirm('Overwrite now') or next end File.rename(src_path, new_path) rescue warn $! end end puts "\ndone." unless @quiet return true end
path 中のファイル名を大文字に変換する.
# File recursiveutils.rb, line 535 def upcase(*path) rename(path){ |i| i.upcase } end
標準入力から Yes or No の回答を得る.
# File recursiveutils.rb, line 559 def confirm(message) count = 5 stderr "#{message}? [y/n] : " loop{ case STDIN.gets when /\Ay(?:es)?\b/i return true when /\An(?:o)?\b/i warn 'quit.' return false else count -= 1 if count > 0 stderr ' Please answer Yes or No. [y/n] : ' else warn 'Give up.' return false end end } end