123456789_123456789_123456789_123456789_123456789_

Module: Find

Relationships & Source Files
Defined in: lib/find.rb

Overview

Module Find supports the top-down traversal of entries in the file system.

Constant Summary

Class Method Summary

  • .find(*paths, ignore_error: true) mod_func

    With a block given, performs a depth-first traversal of each given path in paths; calls the block with each found file or directory path:

  • .prune mod_func

    This method is meaningful only within a block given with .find.

Class Method Details

.find(*paths, ignore_error: true) (mod_func)

With a block given, performs a depth-first traversal of each given path in paths; calls the block with each found file or directory path:

paths = []
Find.find('bin', 'jit') {|path| paths << path }
paths
#### =>
#### ["bin",
####  "bin/gem",
####  "jit",
####  "jit/Cargo.toml",
####  "jit/src",
####  "jit/src/lib.rs"]

Raises an exception if a given path cannot be read.

When keyword argument ignore_error is given as true (the default), certain exceptions during traversal are ignored (i.e., silently rescued): Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG, Errno::EINVAL; when given as false, no exceptions are rescued.

Note that these exceptions may be ignored only in Find traversal code; an exception raised before traversal begins, or raised while in the block is not ignored. Each of the calls below raises an Errno::ENOENT exception that is not ignored:

Find.find('nosuch') { }
Find.find('lib') {|entry| raise Errno::ENOENT }

With no block given, returns a new Enumerator.

[ GitHub ]

  
# File 'lib/find.rb', line 50

def find(*paths, ignore_error: true) # :yield: path
  block_given? or return enum_for(__method__, *paths, ignore_error: ignore_error)

  fs_encoding = Encoding.find("filesystem")

  paths.collect!{|d| raise Errno::ENOENT, d unless File.exist?(d); d.dup}.each do |path|
    path = path.to_path if path.respond_to? :to_path
    enc = path.encoding == Encoding::US_ASCII ? fs_encoding : path.encoding
    ps = [path]
    while file = ps.shift
      catch(:prune) do
        yield file.dup
        begin
          s = File.lstat(file)
        rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG, Errno::EINVAL
          raise unless ignore_error
          next
        end
        if s.directory? then
          begin
            fs = Dir.children(file, encoding: enc)
          rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG, Errno::EINVAL
            raise unless ignore_error
            next
          end
          fs.sort!
          fs.reverse_each {|f|
            f = File.join(file, f)
            ps.unshift f
          }
        end
      end
    end
  end
  nil
end

.prune (mod_func)

This method is meaningful only within a block given with .find.

Inside such a block, "prunes" the traversed file tree by not descending into the current directory:

files = []
Find.find('.') do |path|
  Find.prune if File.basename(path) == 'test'
  next unless File.file?(path) && File.extname(path) == '.rb'
  files << path
end
files.size    # => 6690
files.take(3) # => ["./KNOWNBUGS.rb", "./array.rb", "./ast.rb"]
[ GitHub ]

  
# File 'lib/find.rb', line 108

def prune
  throw :prune
end