Dir 클래스

Dir 클래스

Dir 클래스의 객체는 기본 파일 시스템에 있는 하나의 디렉터리를 나타내요. 크게 두 가지로 구성돼요:

  • 문자열 경로: 객체가 만들어질 때 주어지고, path 메서드가 돌려주는 디렉터리 경로
  • 문자열 항목 모음: 각각 기본 파일 시스템의 디렉터리나 파일 이름인 항목들. 이 항목 이름들은 배열처럼(array-like) 또는 스트림처럼(stream-like) 가져올 수 있어요.

예제 파일 트리

이 페이지의 일부 예제는 다음과 같은 단순 파일 트리를 사용해요:

example/
├── config.h
├── lib/
│ ├── song/
│ │ └── karaoke.rb
│ └── song.rb
└── main.rb

배열처럼 동작하는 Dir

Dir 객체는 배열과 비슷한 면이 있어요:

  • 인스턴스 메서드 children, each, each_child가 있어요.
  • Enumerable 모듈을 포함해요.

스트림처럼 동작하는 Dir

Dir 객체는 스트림과 비슷한 면도 있어요.

스트림은 처음에 읽기용으로 열려 있어요. close 메서드로 수동으로 닫을 수 있고, Dir.open을 블록과 함께 호출했을 때는 블록 종료 시 자동으로 닫혀요. 닫힌 스트림은 더 이상 조작할 수 없고 다시 열 수도 없어요.

스트림은 디렉터리 항목의 인덱스인 위치(position)를 가져요:

  • 초기 위치는 0(첫 항목 앞)이에요.
  • tell(별칭 pos)이 위치를 돌려줘요.
  • pos=가 위치를 설정하고 위치를 돌려줘요.
  • seekpos=와 같지만 self를 돌려줘요(체이닝에 편리).
  • read는 스트림 끝이 아니면 다음 항목을 읽고 위치를 증가시키고, 끝이면 증가시키지 않아요.
  • rewind는 위치를 0으로 설정해요.
dir = Dir.new('example') # => #<Dir:example>
dir.pos # => 0

dir.read # => "."
dir.read # => ".."
dir.read # => "config.h"
dir.pos # => 3

dir.rewind # => #<Dir:example>
dir.pos # => 0

dir.close # => nil
dir.read # Raises IOError.

메서드 한눈에 보기

읽기(Reading): close, pos=, read, rewind, seek

설정(Setting): ::chdir, ::chroot

쿼리(Querying): ::[], ::children, ::empty?, ::entries, ::exist?, ::getwd/pwd, ::glob, ::home, children, fileno, path/to_path, tell/pos

반복(Iterating): ::each_child, ::foreach, each, each_child

기타(Other): ::mkdir, ::new, ::open, ::unlink/delete/rmdir, inspect

출처: Ruby 3.3 API

본문

상수

SYSTMPDIR — 시스템 전체 임시 디렉터리 경로

::[]( *patterns, base: nil, sort: true ) → array

Dir.globpatterns 인자와 base·sort 키워드 값으로 호출해 선택된 항목 이름들의 배열을 돌려줘요.

::chdir(new_dirpath) → 0, ::chdir → 0, ::chdir(new_dirpath) {|new_dirpath| ... } → object, ::chdir {|cur_dirpath| ... } → object

현재 작업 디렉터리를 변경해요. 인자와 블록이 없으면 HOME(정의되어 있으면), 그다음 LOGDIR 환경 변수로 변경해요. 블록이 있으면 일시적으로 변경했다가 예전 작업 디렉터리를 복원하고 블록의 반환값을 돌려줘요:

Dir.pwd # => "/example"
Dir.chdir('..') # => 0
Dir.pwd # => "/"

Dir.chdir('/tmp') do
  Dir.pwd # => "/tmp"
end
Dir.pwd # => "/example"

chdir 블록은 중첩할 수 있어요. 대상 디렉터리가 없으면 예외를 던져요.

::children(dirpath) → array, ::children(dirpath, encoding: 'UTF-8') → array

dirpath에 있는 디렉터리의 항목 이름들('.', '..' 제외)을 배열로 돌려줘요. 주어진 인코딩을 각 항목 이름에 설정해요:

Dir.children('/example') # => ["config.h", "lib", "main.rb"]
Dir.children('/example', encoding: 'US-ASCII').first.encoding
# => #<Encoding:US-ASCII>

::chroot(dirpath) → 0

호출 프로세스의 루트 디렉터리를 dirpath로 변경해요. 권한이 있는 프로세스만 호출할 수 있어요. Linux chroot 참고.

::delete(dirpath), ::rmdir(dirpath) → 0

기본 파일 시스템에서 dirpath의 디렉터리를 제거해요. 비어 있지 않으면 예외를 던져요:

Dir.rmdir('foo') # => 0

::each_child(dirpath) {|entry_name| ... } → nil, ::each_child(dirpath, encoding: 'UTF-8') ...

Dir.foreach와 같지만 '.''..' 항목은 포함하지 않아요.

::empty?(dirpath) → true or false

dirpath가 빈 디렉터리를 가리키는지 돌려줘요:

Dir.empty?('/tmp/foo') # => true
Dir.empty?('/example') # => false

::entries(dirname, encoding: 'UTF-8') → array

dirpath에 있는 디렉터리의 항목 이름들('.', '..' 포함)을 배열로 돌려줘요:

Dir.entries('/example') # => ["config.h", "lib", "main.rb", "..", "."]

::exist?(dirpath) → true or false

dirpath가 기본 파일 시스템의 디렉터리인지 돌려줘요. File.directory?와 같아요:

Dir.exist?('/example') # => true

::fchdir(fd) → 0, ::fchdir(fd) { ... } → object

정수 파일 디스크립터 fd가 가리키는 디렉터리로 현재 작업 디렉터리를 변경해요. POSIX 2008의 fchdir()를 사용하며, 비-POSIX 플랫폼에서는 NotImplementedError를 던져요. chdir보다 time-of-check to time-of-use 취약점을 피할 수 있어요.

::for_fd(fd) → dir

정수 디렉터리 파일 디스크립터 fd가 가리키는 디렉터리를 나타내는 새 Dir 객체를 돌려줘요. 반환된 객체는 경로와 연결되어 있지 않아요(pathnil).

::foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil

dirpath의 각 항목 이름으로 블록을 호출하고 주어진 인코딩을 설정해요. 블록이 없으면 Enumerator를 돌려줘요.

::getwd, ::pwd → string

현재 작업 디렉터리 경로를 돌려줘요:

Dir.chdir("/tmp") # => 0
Dir.pwd # => "/tmp"

::glob(*patterns, flags: 0, base: nil, sort: true) → array, ::glob(...) {|entry_name| ... } → nil

인자들이 선택한 항목 이름들의 배열 entry_names을 형성해요. patterns는 정규식이 아니라 문자열 패턴(또는 그 배열)이에요.

블록이 없으면 배열, 블록이 있으면 각 항목 이름으로 블록을 호출하고 nil을 돌려줘요. base는 기준 디렉터리, sort는 정렬 여부를 정해요.

패턴 메타문자:

  • '*': 항목 이름의 어떤 부분 문자열과도 매칭(정규식 /.*/mx와 비슷). 'c*'는 c로 시작, '*c'는 c로 끝나는 이름. 점(.)으로 시작하는 숨김 파일은 기본적으로 매칭하지 않아요.
  • '**': 슬래시 '/'가 뒤따르면 재귀적으로 매칭.
  • '?': 어떤 한 글자와 매칭(/./와 비슷).
  • '[set]': 문자열 집합의 한 문자와 매칭(정규식 문자 클래스처럼, '[^a-z]' 부정 포함).
  • '{abc,xyz}': abc 또는 xyz와 매칭(정규식 alternation).
  • '\\': 다음 메타문자를 이스케이프. (Windows에서 문자열 패턴에 백슬래시는 못 쓰고 Dir['c:/foo*']처럼 써요.)
Dir.glob('config.?') # => ["config.h"]
Dir.glob('*.{rb,h}') # => ["main.rb", "config.h"]
Dir.glob('**/*.rb')
# => ["lib/song/karaoke.rb", "lib/song.rb", "main.rb"]
Dir.glob('**/*.rb', base: 'lib') # => ["song/karaoke.rb", "song.rb"]

플래그(Flags): flagsFile::Constants 모듈의 상수들을 bitwise OR한 값이에요. 이 메서드에 해당하는 플래그는 File::FNM_DOTMATCH(숨김 파일 포함), File::FNM_EXTGLOB({a,b} 확장 활성화), File::FNM_NOESCAPE(백슬래시 이스케이프 비활성), File::FNM_PATHNAME(*·?가 디렉터리 구분자 비매칭), File::FNM_SHORTNAME(Windows 전용)이에요.

::home(user_name = nil) → dirpath

주어진 사용자(또는 현재 로그인 사용자)의 홈 디렉터리 경로를 돌려줘요:

Dir.home # => "/home/me"
Dir.home('root') # => "/root"

::mkdir(dirpath, permissions = 0775) → 0

dirpath에 권한 permissions로 디렉터리를 만들고 0을 돌려줘요. permissions는 Windows에서 무시돼요.

::mktmpdir(prefix_suffix=nil, *rest, **options) { |dup| ... }

임시 디렉터리를 만들어요. 디렉터리 이름의 접두사/접미사는 prefix_suffix로 지정돼요(문자열이면 접두사, 배열이면 [접두사, 접미사]). 블록이 있으면 디렉터리 경로를 넘기고 종료 시 FileUtils.remove_entry로 제거한 뒤 블록 값을 돌려줘요. 블록이 없으면 경로를 돌려주고 디렉터리를 제거하지 않아요.

::new(dirpath) → dir, ::new(dirpath, encoding: nil) → dir

dirpath의 디렉터리용 새 Dir 객체를 돌려줘요. encodingnil이면 파일 시스템 인코딩을 사용해요:

Dir.new('.') # => #<Dir:.>

::open(dirpath) → dir, ::open(dirpath, encoding: nil) → dir, ::open(dirpath) {|dir| ... } → object

dirpath의 디렉터리용 새 Dir 객체 dir을 만들어요. 블록이 없으면 Dir.new(dirpath, encoding)과 같고, 블록이 있으면 블록에 dir을 넘기고 종료 시 닫은 뒤 블록 값을 돌려줘요:

Dir.open('.') {|dir| dir.inspect } # => "#<Dir:.>"

::tmpdir()

운영체제의 임시 파일 경로를 돌려줘요. (require 'tmpdir' 후 사용)

children → array

self의 항목 이름들('.', '..' 제외)을 배열로 돌려줘요:

dir = Dir.new('/example')
dir.children # => ["config.h", "lib", "main.rb"]

close → nil

self의 스트림이 열려 있으면 닫고 nil을 돌려줘요. 이미 닫혀 있으면 무시해요:

dir = Dir.new('example')
dir.close # => nil
dir.read # Raises IOError.

each {|entry_name| ... } → self, each → enumerator

self의 각 항목(, '.', '..' 포함)으로 블록을 호출하고 self를 돌려줘요.

each_child {|entry_name| ... } → self

self의 각 항목('.', '..' 제외)으로 블록을 호출해요.

fileno → integer

self의 정수 파일 디스크립터를 돌려줘요.

inspect → string

self에 대한 문자열 설명을 돌려줘요.

path → string, to_path → string

self를 만드는 데 사용한 경로를 돌려줘요.

pos → integer, tell → integer

self의 디렉터리 스트림에서 현재 위치의 정수를 돌려줘요.

pos= → integer

self의 디렉터리 스트림에서 위치를 설정하고 위치를 돌려줘요(값이 범위 밖이면 무시).

read → string or nil

self의 디렉터리 스트림에서 다음 항목을 읽어 돌려줘요. 끝이면 nil.

rewind → self

self의 스트림 위치를 첫 항목으로 설정해요.

seek(pos) → self

self의 스트림 위치를 주어진 오프셋의 항목으로 설정하고 self를 돌려줘요.

더 알아보기

  • Dir.glob은 파일 트리를 검색할 때 정말 자주 쓰는 메서드예요. Dir['*.rb'] 같은 ::[] 축약형도 기억해 두면 좋아요.
  • 블록과 함께 쓰는 Dir.chdir은 작업 디렉터리를 안전하게 잠시 바꿨다가 되돌리는 패턴이라서 파일 처리 코드에 자주 등장해요.