module Find - Documentation for Ruby 4.0 (original) (raw)

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
else next end else total_size += FileTest.size(path) end end

Constants

VERSION

The version string

Public Class Methods

Source

def find(*paths, ignore_error: true) 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

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.

Source

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

Source

def find(*paths, ignore_error: true) 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

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.

Source

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.