Модуль Find
Модуль Find поддерживает итерацию сверху вниз по набору путей к файлам.
Например, для подсчёта общего размера всех файлов в домашнем каталоге, игнорируя файлы в каталогах с именем «точка» (например, $HOME/.ssh):
require 'find'
total_size = 0
Find.find(ENV["HOME"]) do |path|
if FileTest.directory?(path)
if File.basename(path)[0] == ?.
Find.prune # Don't look any further into this directory.
else
next
end
else
total_size += FileTest.size(path)
end
end
Публичные методы класса
# 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 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.taint
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.entries(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|
next if f == "." or f == ".."
f = File.join(file, f)
ps.unshift f.untaint
}
end
end
end
end
nil
end Вызывает связанный блок с именем каждого файла и каталога, перечисленных в качестве аргументов, а затем рекурсивно в их подкаталогах и так далее.
Возвращает перечислитель, если блок не задан.
См. документацию модуля Find для примера.
# File lib/find.rb, line 84 def prune throw :prune end
Пропускает текущий файл или каталог, перезапуская цикл со следующей записью. Если текущий файл является каталогом, этот каталог не будет рекурсивно обработан. Имеет смысл только внутри блока, связанного с ::find.
См. документацию модуля Find для примера.
Приватные методы экземпляра
# 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 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.taint
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.entries(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|
next if f == "." or f == ".."
f = File.join(file, f)
ps.unshift f.untaint
}
end
end
end
end
nil
end Вызывает связанный блок с именем каждого файла и каталога, перечисленных в качестве аргументов, а затем рекурсивно в их подкаталогах и так далее.
Возвращает перечислитель, если блок не задан.
См. документацию модуля Find для примера.
# File lib/find.rb, line 84 def prune throw :prune end
Пропускает текущий файл или каталог, перезапуская цикл со следующей записью. Если текущий файл является каталогом, этот каталог не будет рекурсивно обработан. Имеет смысл только внутри блока, связанного с ::find.
См. документацию модуля Find для примера.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.