модуль 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 37
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.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.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.untaint
}
end
end
end
end
nil
end Вызывает связанный блок с именем каждого файла и каталога, переданного в качестве аргументов, а затем рекурсивно для их подкаталогов и так далее.
Возвращает перечислитель, если блок не задан.
См. документацию по модулю Find для примера.
# File lib/find.rb, line 82 def prune throw :prune end
Пропускает текущий файл или каталог, перезапуская цикл со следующей записью. Если текущий файл — каталог, то этот каталог не будет рекурсивно обработан. Имеет смысл только внутри блока, связанного с ::find.
См. документацию по модулю Find для примера.
Приватные методы экземпляра
# File lib/find.rb, line 37
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.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.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.untaint
}
end
end
end
end
nil
end Вызывает связанный блок с именем каждого файла и каталога, переданного в качестве аргументов, а затем рекурсивно для их подкаталогов и так далее.
Возвращает перечислитель, если блок не задан.
См. документацию по модулю Find для примера.
# File lib/find.rb, line 82 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.