Class RecursiveUtils::Rename
In: recursiveutils.rb
Parent: Object

Summary

再帰処理機能, 文字コード変換機能を実装した Ruby 版 rename.

Example

  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" を "_" に置換

Methods

Public Methods

初期化:new
ファイル操作:rename, gsub, upcase, downcase, convert
設定:figure=, number=

Private Methods

確認:confirm

Reference Tool

rename.rb:www.ep.sci.hokudai.ac.jp/~daktu32/DOC/ruby/works/ruby_works.htm

Methods

confirm   convert   downcase   figure=   gsub   new   number=   rename   upcase  

Included Modules

FullPathList::Flag LocaleFilter::PrintWrapper

Attributes

escape  [RW]  変換パターンの正規表現のメタ文字を保護する.
figure  [R]  設定された桁数の連番に置換する.
force  [RW]  確認無しで処理を実行する.
name_type  [RW]  処理対象を限定する. 先頭の文字が b (basename), e (extname) の時のみ有効.
noop  [RW]  変換処理を行わない.
number  [R]  連番の初期値. デフォルトは 1.
quiet  [RW]  メッセージを抑制する.

Public Class methods

新規オブジェクトを作成する. オプションの意味は FullPathList::FlagRenameAttributes を参照する事.

[Source]

# 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

Public Instance methods

path 中のファイル名の文字コードを code に変換する.

[Source]

# 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 中のファイル名を小文字に変換する.

[Source]

# File recursiveutils.rb, line 540
    def downcase(*path)
      rename(path){ |i| i.downcase }
    end

@figure の設定用メソッド. num が 負の場合は例外 ArgumentError を返す.

[Source]

# 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 に変換する.

[Source]

# 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 を返す.

[Source]

# File recursiveutils.rb, line 410
    def number=(num)
      num = Integer(num)
      raise ArgumentError, "#{num}: Invalid size."  if num < 0
      @number = num
    end

配列 list を元に作成した処理対象をブロックで変換する.

[Source]

# 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 中のファイル名を大文字に変換する.

[Source]

# File recursiveutils.rb, line 535
    def upcase(*path)
      rename(path){ |i| i.upcase }
    end

Private Instance methods

標準入力から Yes or No の回答を得る.

[Source]

# 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

[Validate]