Module FileUtils
In: lib/facets/standard/facets/fileutils/slice.rb
lib/facets/standard/facets/fileutils/outofdate.rb
lib/facets/standard/facets/fileutils/ln_r.rb
lib/facets/standard/facets/fileutils/stage.rb
lib/facets/standard/facets/fileutils/whereis.rb
lib/facets/standard/facets/fileutils/which.rb
lib/facets/standard/facets/fileutils/safe_ln.rb
lib/facets/standard/facets/fileutils/amass.rb
lib/facets/standard/facets/fileutils/wc.rb
lib/facets/standard/facets/fileutils/cp_rx.rb

Methods

amass   copy_entryx   cp_rx   head   link_entry   ln_r   out_of_date?   outofdate?   safe_ln   slice   stage   tail   wc   whereis   which  

Classes and Modules

Module FileUtils::DryRun
Module FileUtils::NoWrite
Module FileUtils::Verbose

Constants

OPT_TABLE = {} unless const_defined?(:OPT_TABLE)
Win32Exts = %w{.exe .com .bat .cmd}
Win32Exts = %w{.exe .com .bat .cmd}
LINKING_SUPPORTED = [true]

External Aliases

uptodate? -> up_to_date?
  Alias for uptodate?

Public Instance methods

An intergrated glob like method that take a set of include globs, exclude globs and ignore globs to produce a collection of paths.

The ignore_globs differ from exclude_globs in that they match by the basename of the path rather than the whole pathname.

TODO: Should ignore be based on any portion of the path, not just the basename?

[Source]

# File lib/facets/standard/facets/fileutils/amass.rb, line 13
  def amass(include_globs, exclude_globs=[], ignore=[])
    include_files = include_globs.flatten.map{ |g| Dir.glob(g) }.flatten.uniq
    exclude_files = exclude_globs.flatten.map{ |g| Dir.glob(g) }.flatten.uniq

    include_globs = include_globs.map{ |f| File.directory?(f) ? File.join(f, '**/*') : f } # Recursive!
    exclude_globs = exclude_globs.map{ |f| File.directory?(f) ? File.join(f, '**/*') : f } # Recursive!

    include_files = include_globs.flatten.map{ |g| Dir.glob(g) }.flatten.uniq
    exclude_files = exclude_globs.flatten.map{ |g| Dir.glob(g) }.flatten.uniq

    files = include_files - exclude_files

    files = files.reject{ |f| ignore.any?{ |x| File.fnmatch?(x, File.basename(f)) } }

    files
  end

Like FileUtils.copy_entry, but takes a filter proc that can return false to skip a file.

Note that if the filter rejects a subdirectory then everything within that subdirectory is automatically skipped as well.

[Source]

# File lib/facets/standard/facets/fileutils/cp_rx.rb, line 32
  def copy_entryx(src, dest, filter, preserve = false, dereference_root = false, remove_destination = false)
          Entry_.new(src, nil, dereference_root).traverse do |ent|
                  if filter.call(ent.path) then
                          destent = Entry_.new(dest, ent.rel, false)
                          File.unlink destent.path if remove_destination && File.file?(destent.path)
                          ent.copy destent.path
                          ent.copy_metadata(destent.path) if preserve
                  end
          end
  end

Like FileUtils.cp_r, but takes a filter proc that can return false to skip a file:

  cp_rx "bigDirectoryTree", "dest", {:noop => true} do |name|
     /dontCopyThis$/.match(name)
  end

Note that if the filter rejects a subdirectory then everything within that subdirectory is automatically skipped as well.

[Source]

# File lib/facets/standard/facets/fileutils/cp_rx.rb, line 16
  def cp_rx(src, dest, options = {}, &filter)
          fu_check_options(options, OPT_TABLE['cp_r'])
    if options[:verbose]
            fu_output_message("cp -r#{options[:preserve] ? 'p' : ''}#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}")
    end
          return if options[:noop]
          fu_each_src_dest(src, dest) do |s, d|
                  copy_entryx(s, d, filter, options[:preserve], options[:dereference_root], options[:remove_destination])
          end
  end

In block form, yields the first number of lines of file filename. In non-block form, it returns an array of the first number of lines:

  # Returns first 10 lines of 'myfile'
  FileUtils.head("myfile", 10)

[Source]

# File lib/facets/standard/facets/fileutils/slice.rb, line 25
  def head(filename,lines) #:yield:
    a = []
    IO.foreach(filename){|line|
        break if lines <= 0
        lines -= 1
        if block_given?
          yield line
        else
          a << line
        end
    }
    return a.empty? ? nil : a
  end

Hard links a file system entry src to dest. If src is a directory, this method links its contents recursively.

Both of src and dest must be a path name. src must exist, dest must not exist.

If dereference_root is true, this method dereference tree root.

If remove_destination is true, this method removes each destination file before copy.

[Source]

# File lib/facets/standard/facets/fileutils/ln_r.rb, line 55
    def link_entry(src, dest, dereference_root = false, remove_destination = false)
      Entry_.new(src, nil, dereference_root).traverse do |ent|
        destent = Entry_.new(dest, ent.rel, false)
        File.unlink destent.path if remove_destination && File.file?(destent.path)
        ent.link destent.path
      end
    end

Options: noop verbose dereference_root remove_destination

Hard link src to dest. If src is a directory, this method links all its contents recursively. If dest is a directory, links src to +dest/src+.

src can be a list of files.

  # Installing ruby library "mylib" under the site_ruby
  FileUtils.rm_r site_ruby + '/mylib', :force
  FileUtils.ln_r 'lib/', site_ruby + '/mylib'

  # Examples of copying several files to target directory.
  FileUtils.ln_r %w(mail.rb field.rb debug/), site_ruby + '/tmail'
  FileUtils.ln_r Dir.glob('*.rb'), '/home/aamine/lib/ruby', :noop => true, :verbose => true

  # If you want to copy all contents of a directory instead of the
  # directory itself, c.f. src/x -> dest/x, src/y -> dest/y,
  # use following code.
  FileUtils.ln_r 'src/.', 'dest'     # cp_r('src', 'dest') makes src/dest,
                                     # but this doesn't.

TODO: Why —remove-destination and not just —force?

[Source]

# File lib/facets/standard/facets/fileutils/ln_r.rb, line 29
    def ln_r(src, dest, options = {})
      fu_check_options options, OPT_TABLE['ln_r']
      fu_output_message "ln -r#{options[:remove_destination] ? ' --remove-destination' : ''} #{[src,dest].flatten.join ' '}" if options[:verbose]
      return if options[:noop]
      options = options.dup
      options[:dereference_root] = true unless options.key?(:dereference_root)
      fu_each_src_dest(src, dest) do |s, d|
        link_entry s, d, options[:dereference_root], options[:remove_destination]
      end
    end
out_of_date?(path, *sources)

Alias for outofdate?

The opposite of uptodate?

[Source]

# File lib/facets/standard/facets/fileutils/outofdate.rb, line 7
  def outofdate?(path, *sources)
    #return true unless File.exist?(path)
    ! uptodate?(path, sources.flatten)
  end

Attempt to do a normal file link, but fall back to a copy if the link fails.

CREDIT: Jim Weirich

[Source]

# File lib/facets/standard/facets/fileutils/safe_ln.rb, line 13
  def safe_ln(*args)
    unless LINKING_SUPPORTED[0]
      cp(*args)
    else
      begin
        ln(*args)
      rescue Errno::EOPNOTSUPP
        LINKING_SUPPORTED[0] = false
        cp(*args)
      end
    end
  end

In block form, yields lines from-to. In non-block form, returns an array of lines from-to:

  # Returns lines 8-12 of 'myfile'
  FileUtils.body("myfile",8,12)

CREDIT Shashank Date, via Daniel Berger.

[Source]

# File lib/facets/standard/facets/fileutils/slice.rb, line 15
  def slice(filename,from,to) #:yield:
    IO.readlines(filename)[from-1..to-1]
  end

Stage by hard linking included files to a stage directory.

stage_directory - Where to stage the files source_directory - Where to find files to stage files - Files to link in stage relative to source

TODO: Rename to link_stage or something less likely to name clash? TODO: Add options for :verbose, :noop and :dryrun ?

[Source]

# File lib/facets/standard/facets/fileutils/stage.rb, line 15
  def stage(stage_directory, source_directory, files, options={})
    return stage_directory if options[:noop] || options[:dryrun]

    stage_directory, source_directory = stage_directory.to_s, source_directory.to_s
    ## ensure existance of staging area
    rm_r(stage_directory) if File.directory?(stage_directory)
    mkdir_p(stage_directory)
    ## link files into staging area
    files.each do |f|
      src  = File.join(source_directory, f)
      file = File.join(stage_directory, f)
      if File.directory?(src)
        mkdir_p(file) unless File.exist?(file)
      else
        fdir = File.dirname(file)
        mkdir_p(fdir) unless File.exist?(fdir)
        unless File.exist?(file) and File.mtime(file) >= File.mtime(src)
          ln(src, file) #safe_ln ?
        end
      end
    end
    return stage_directory
  end

In block form, yields the last number of lines of file filename. In non-block form, it returns the lines as an array.

Note that this method slurps the entire file, so I don‘t recommend it for very large files. If you want an advanced form of tail, I suggest using file-tail, by Florian Frank (available on the RAA):

  # Returns last 3 lines of 'myfile'
  FileUtils.tail("myfile",3)

And no tail -f.

[Source]

# File lib/facets/standard/facets/fileutils/slice.rb, line 50
  def tail(filename,lines) #:yield
    IO.readlines(filename).reverse[0..lines-1].reverse
  end

With no arguments, returns a four element array consisting of the number of bytes, characters, words and lines in filename, respectively.

Valid options are bytes, characters (or just ‘chars’), words and lines:

  # Return the number of words in 'myfile'
  FileUtils.wc("myfile",'words')

CREDIT: Daniel J. Berger

[Source]

# File lib/facets/standard/facets/fileutils/wc.rb, line 17
  def wc(filename,option='all')
    option.downcase!
    valid = %w/all bytes characters chars lines words/

    unless valid.include?(option)
        raise "Invalid option: '#{option}'"
    end

    n = 0
    if option == 'lines'
        IO.foreach(filename){ n += 1 }
        return n
    elsif option == 'bytes'
        File.open(filename){ |f|
          f.each_byte{ n += 1 }
        }
        return n
    elsif option == 'characters' || option == 'chars'
        File.open(filename){ |f|
          while f.getc
              n += 1
          end
        }
        return n
    elsif option == 'words'
        IO.foreach(filename){ |line|
          n += line.split.length
        }
        return n
    else
        bytes,chars,lines,words = 0,0,0,0
        IO.foreach(filename){ |line|
          lines += 1
          words += line.split.length
          chars += line.split('').length
        }
        File.open(filename){ |f|
          while f.getc
              bytes += 1
          end
        }
        return [bytes,chars,words,lines]
    end
  end

In block form, yields each ((program)) within ((path)). In non-block form, returns an array of each ((program)) within ((path)). Returns (({nil})) if not found.

On the MS Windows platform, it looks for executables ending with .exe, .bat and .com, which you may optionally include in the program name:

   FileUtils.whereis("ruby")  #=> ['/usr/local/bin/ruby','/opt/bin/ruby']

CREDIT: Daniel J. Berger

[Source]

# File lib/facets/standard/facets/fileutils/whereis.rb, line 25
  def whereis(prog, path=ENV['PATH']) #:yield:
    dirs = []
    path.split(File::PATH_SEPARATOR).each{|dir|
        # Windows checks against specific extensions
        if File::ALT_SEPARATOR
          if prog.include?('.')
              f = File.join(dir,prog)
              if File.executable?(f) && !File.directory?(f)
                if block_given?
                    yield f.gsub(/\//,'\\')
                else
                    dirs << f.gsub(/\//,'\\')
                end
              end
          else
              Win32Exts.find_all{|ext|
                f = File.join(dir,prog+ext)
                if File.executable?(f) && !File.directory?(f)
                    if block_given?
                      yield f.gsub(/\//,'\\')
                    else
                      dirs << f.gsub(/\//,'\\')
                    end
                end
              }
          end
        else
          f = File.join(dir,prog)
          # Avoid /usr/lib/ruby, for example
          if File.executable?(f) && !File.directory?(f)
              if block_given?
                yield f
              else
                dirs << f
              end
          end
        end
    }
    dirs.empty? ? nil : dirs
  end

Looks for the first occurrence of program within path.

On the MS Windows platform, it looks for executables ending with .exe, .bat and .com, which you may optionally include in the program name. Returns nil if not found.

CREDIT: Daniel J. Berger, Michael Granger

[Source]

# File lib/facets/standard/facets/fileutils/which.rb, line 27
  def which(prog, path=ENV['PATH'])
    path.split(File::PATH_SEPARATOR).each {|dir|
      # Windows checks against specific extensions
      if File::ALT_SEPARATOR
        ext = Win32Exts.find{|ext|
          if prog.include?('.') # Assume extension already included
            f = File.join(dir,prog)
          else
            f = File.join(dir,prog+ext)
          end
          File.executable?(f) && !File.directory?(f)
        }
        if ext
          # Use backslashes, not forward slashes
          if prog.include?('.') # Assume extension already included
            f = File.join( dir, prog ).gsub(/\//,'\\')
          else
            f = File.join( dir, prog + ext ).gsub(/\//,'\\')
          end
          return f
        end
      else
        f = File.join(dir,prog)
        # Avoid /usr/lib/ruby, for example
        if File.executable?(f) && !File.directory?(f)
          return File::join( dir, prog )
        end
      end
    }
    nil
  end

[Validate]