Find 모듈
Find 모듈 (Find)
파일 경로 집합을 위에서 아래로(top-down) 순회하는 기능을 제공하는 모듈이에요. 디렉토리 트리를 재귀적으로 돌며 각 파일·디렉토리마다 블록을 실행해요.
예를 들어 홈 디렉토리 아래 모든 파일 크기의 합을 구하되, "점(dot)"으로 시작하는 디렉토리(예: $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
출처: Ruby 3.3 API
본문
Find.find는 인자로 준 경로에서 시작해 하위 디렉토리까지 재귀적으로 탐색해요. 탐색을 끊고 싶은 디렉토리가 있으면 Find.prune으로 그 지점부터 건너뛸 수 있어요.
상수 (Constants)
VERSION— 모듈 버전
::find (Public Class Method)
find(*paths, ignore_error: true) { |path| ... } — 인자로 나열된 모든 파일·디렉토리 이름으로 블록을 호출하고, 그 하위 디렉토리로 재귀하며 같은 작업을 반복해요. 블록이 없으면 인자 대신 열거자(enumerator)를 돌려줘요. ignore_error: true일 때 접근 불가·없는 경로 같은 오류는 무시하고 계속 진행해요.
# File lib/find.rb, line 40
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 (Public Class Method)
prune() — 현재 파일이나 디렉토리를 건너뛰고, 루프를 다음 항목부터 다시 시작해요. 현재 항목이 디렉토리면 그 디렉토리로는 재귀 진입하지 않아요. Find::find와 연결된 블록 안에서만 의미가 있어요.
# File lib/find.rb, line 85
def prune
throw :prune
end
위 예시에서 .ssh 같은 숨김 디렉토리를 만나면 Find.prune을 호출해 그 안으로 내려가지 않게 해요. 덕분에 불필요한 탐색을 끊을 수 있어요.