module Find

The Find module supports the top-down traversal of a set of file paths.

For example, to total the size of all files under your home directory, ignoring anything in a “dot” directory (e.g. $HOME/.ssh):

require 'find'

total_size = 0

Find.find(ENV["HOME"]) do |path|
  if FileTest.directory?(path)
    if File.basename(path).start_with?('.')
      Find.prune       # Don't look any further into this directory.
    else
      next
    end
  else
    total_size += FileTest.size(path)
  end
end

Public Class Methods

find(*paths, ignore_error: true) { |path| ... } Show source
# File lib/find.rb, line 38
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
          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
            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

Calls the associated block with the name of every file and directory listed as arguments, then recursively on their subdirectories, and so on.

Returns an enumerator if no block is given.

See the Find module documentation for an example.

prune() Show source
# File lib/find.rb, line 83
def prune
  throw :prune
end

Skips the current file or directory, restarting the loop with the next entry. If the current file is a directory, that directory will not be recursively entered. Meaningful only within the block associated with Find::find.

See the Find module documentation for an example.

Private Instance Methods

find(*paths, ignore_error: true) { |path| ... } Show source
# File lib/find.rb, line 38
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
          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
            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

Calls the associated block with the name of every file and directory listed as arguments, then recursively on their subdirectories, and so on.

Returns an enumerator if no block is given.

See the Find module documentation for an example.

prune() Show source
# File lib/find.rb, line 83
def prune
  throw :prune
end

Skips the current file or directory, restarting the loop with the next entry. If the current file is a directory, that directory will not be recursively entered. Meaningful only within the block associated with Find::find.

See the Find module documentation for an example.

Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.