Dir 클래스

Dir 클래스

Dir 클래스의 객체는 기반 파일시스템의 디렉터리 하나를 나타내요. 크게 두 가지로 이뤄져 있어요:

  • 객체를 만들 때 주어지는 문자열 path — 기반 파일시스템의 디렉터리를 가리켜요. path 메서드가 그 경로를 돌려줘요.
  • 문자열 *항목 이름(entry name)*들의 모음 — 각 항목은 기반 파일시스템의 디렉터리나 파일 이름이에요. 항목 이름은 배열처럼 또는 스트림처럼 방식으로 가져올 수 있어요.

예시에 대하여

이 페이지의 몇몇 예시는 이런 단순한 파일 트리를 써요:

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

다른 예시들은 Ruby 프로젝트 자체의 파일 트리를 사용해요.

배열 같은 Dir

Dir 객체는 어떤 면에서 배열과 같아요:

  • 인스턴스 메서드 children, each, each_child를 갖고 있어요.
  • 모듈 Enumerable을 include해요.

스트림 같은 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.read # => "lib"
dir.read # => "main.rb"
dir.pos  # => 5
dir.read # => nil
dir.pos  # => 5

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

dir.pos = 3 # => 3
dir.pos     # => 3

dir.seek(4) # => #<Dir:example>
dir.pos     # => 4

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

여기 있는 것들 (What's Here)

먼저, 다른 곳에 있는 것들. Dir 클래스는:

  • Object 클래스에서 상속받아요.
  • 수십 개의 추가 메서드를 제공하는 모듈 Enumerable을 include해요.

여기서 Dir 클래스는 다음 용도에 유용한 메서드들을 제공해요:

  • 읽기(Reading)
  • 설정(Setting)
  • 조회(Querying)
  • 반복(Iterating)
  • 기타(Other)

읽기

  • close: self의 디렉터리 스트림을 닫아요.
  • pos=: self의 디렉터리 스트림 위치를 설정해요.
  • read: self의 디렉터리 스트림에서 다음 항목을 읽고 돌려줘요.
  • rewind: self의 디렉터리 스트림 위치를 첫 항목으로 설정해요.
  • seek: self의 디렉터리 스트림 위치를 주어진 오프셋의 항목으로 설정해요.

설정

  • ::chdir: 현재 프로세스의 작업 디렉터리를 주어진 디렉터리로 바꿔요.
  • ::chroot: 현재 프로세스의 파일시스템 루트를 주어진 디렉터리로 바꿔요.

조회

  • ::[]: 플래그를 넘길 수 없다는 점만 빼고 ::glob과 같아요.
  • ::children: 주어진 디렉터리의 자식(파일과 디렉터리 모두) 이름 배열을 돌려줘요. ...은 포함하지 않아요.
  • ::empty?: 주어진 경로가 빈 디렉터리인지 돌려줘요.
  • ::entries: 주어진 디렉터리의 자식 이름 배열을 돌려줘요. ...을 포함해요.
  • ::exist?: 주어진 경로가 디렉터리인지 돌려줘요.
  • ::getwd(pwd 별칭): 현재 작업 디렉터리 경로를 돌려줘요.
  • ::glob: 주어진 패턴과 플래그에 일치하는 파일 경로 배열을 돌려줘요.
  • ::home: 주어진 사용자 또는 현재 사용자의 홈 디렉터리 경로를 돌려줘요.
  • children: self의 자식 이름 배열. ...은 포함하지 않아요.
  • fileno: self의 정수 파일 디스크립터를 돌려줘요.
  • path(to_path 별칭): self를 만드는 데 쓰인 경로를 돌려줘요.
  • tell(pos 별칭): self의 디렉터리 스트림의 정수 위치를 돌려줘요.

반복

  • ::each_child: 주어진 디렉터리의 각 항목으로 주어진 블록을 호출해요. ...은 포함하지 않아요.
  • ::foreach: 주어진 디렉터리의 각 항목으로 주어진 블록을 호출해요. ...을 포함해요.
  • each: self의 각 항목으로 주어진 블록을 호출해요. ...을 포함해요.
  • each_child: self의 각 항목으로 주어진 블록을 호출해요. ...은 포함하지 않아요.

기타

  • ::mkdir: 주어진 경로에 (선택 권한으로) 디렉터리를 만들어요.
  • ::new: 주어진 경로에 (선택 인코딩으로) 새 Dir을 돌려줘요.
  • ::open: ::new와 같지만, 블록을 주면 블록에 Dir을 넘겨 블록 탈출 시 닫아요.
  • ::unlink(::delete, ::rmdir 별칭): 주어진 디렉터리를 제거해요.
  • inspect: self의 문자열 설명을 돌려줘요.

클래스 메서드

  • Dir[*patterns, base: nil, sort: true] → array — 인자 patterns와 키워드 인자 base·sort의 값으로 Dir.glob을 호출하고, 선택된 항목 이름 배열을 돌려줘요.

  • chdir(new_dirpath) → 0 — 현재 작업 디렉터리를 바꿔요.

    인자 new_dirpath와 블록 없이: 주어진 dirpath로 변경:

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

    인자도 블록도 없이: HOME 환경 변수 값으로 변경, 정의돼 있으면; 아니면 LOGDIR 환경 변수 값으로; 아니면 변경하지 않아요.

    인자 new_dirpath와 블록과 함께: 작업 디렉터리를 임시로 변경해요. 블록을 인자와 함께 호출하고, 주어진 디렉터리로 변경하고, 블록을 실행하고(새 경로 넘김), 이전 작업 디렉터리를 복원하고, 블록의 반환값을 돌려줘요.

    Dir.chdir('/var/spool/mail')
    Dir.pwd   # => "/var/spool/mail"
    Dir.chdir('/tmp') do
      Dir.pwd # => "/tmp"
    end
    Dir.pwd   # => "/var/spool/mail"
    

    블록 있는 Dir.chdir 호출은 중첩할 수 있어요. 멀티스레드 프로그램에서 다른 스레드가 하나 열고 있는 동안 또 다른 스레드가 chdir 블록을 열려고 하면, 또는 chdir에 넘긴 블록 안에서 블록 없는 chdir 호출이 일어나면 오류가 발생해요. 대상 디렉터리가 없으면 예외를 던져요.

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

    Dir.children('/example') # => ["config.h", "lib", "main.rb"]
    
  • chroot(dirpath) → 0 — 호출 프로세스의 루트 디렉터리를 dirpath로 변경해요. 새 루트 디렉터리는 '/'로 시작하는 경로명에 쓰여요. 루트 디렉터리는 호출 프로세스의 모든 자식이 상속해요. 권한 있는 프로세스만 chroot를 호출할 수 있어요.

  • rmdir(dirpath) → 0 — 기반 파일시스템에서 dirpath의 디렉터리를 제거해요. 디렉터리가 비어 있지 않으면 예외.

    Dir.rmdir('foo') # => 0
    
  • each_child(dirpath) {|entry_name| ... } → nilDir.foreach와 같지만 '.''..' 항목이 포함되지 않아요.

  • empty?(dirpath) → true or falsedirpath가 빈 디렉터리를 가리키는지 돌려줘요.

    dirpath = '/tmp/foo'
    Dir.mkdir(dirpath)
    Dir.empty?(dirpath)            # => true
    Dir.empty?('/example')         # => false
    
  • entries(dirname, encoding: 'UTF-8') → arraydirpath 디렉터리의 항목 이름 배열을 돌려줘요. 각 항목에 주어진 인코딩을 설정해요.

    Dir.entries('/example') # => ["config.h", "lib", "main.rb", "..", "."]
    
  • exist?(dirpath) → true or falsedirpath가 기반 파일시스템의 디렉터리인지 돌려줘요. File.directory?와 같아요.

    Dir.exist?('/example')         # => true
    Dir.exist?('/nosuch')          # => false
    
  • fchdir(fd) → 0 — 현재 작업 디렉터리를 정수 파일 디스크립터 fd로 지정된 디렉터리로 변경해요. UNIX 소켓이나 자식 프로세스로 파일 디스크립터를 넘길 때 chdir 대신 fchdir을 쓰면 time-of-check-time-of-use 취약점을 피할 수 있어요. 블록과 함께: 작업 디렉터리를 임시로 변경해요. 이 메서드는 POSIX 2008의 fchdir() 함수를 사용하며, 비-POSIX 플랫폼에서는 구현되지 않아요 (NotImplementedError 발생).

  • for_fd(fd) → dir — 주어진 정수 디렉터리 파일 디스크립터 fd로 지정된 디렉터리를 나타내는 새 Dir 객체를 돌려줘요. 돌려받은 d1은 연관된 경로가 없어요 (d1.path # => nil). fdopendir() 함수를 사용하며 비-POSIX 플랫폼에서는 미구현.

  • foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nildirpath 디렉터리의 각 항목 이름으로 블록을 호출해요. 각 entry_name에 주어진 인코딩을 설정해요. 블록이 없으면 enumerator를 돌려줘요.

  • pwd → string — 현재 작업 디렉터리 경로를 돌려줘요: Dir.pwd # => "/tmp"

  • glob(patterns, flags: 0, base: nil, sort: true) → array — 인자로 선택된 항목 이름 entry_names의 배열을 구성해요. 인자 patterns는 문자열 패턴 또는 문자열 패턴 배열이에요 (정규식이 아니라는 점 유의). 블록 없이 배열 entry_names를 돌려주고, 블록과 함께 각 항목 이름으로 블록을 호출하고 nil을 돌려줘요.

    키워드 인자 base가 주어지면 그 값이 베이스 디렉터리를 지정해요. 각 패턴 문자열은 베이스 디렉터리 기준의 항목을 지정해요. 기본값은 '.'이고, 결과의 항목 이름에는 베이스 디렉터리가 앞에 붙지 않아요. 키워드 sort의 값이 정렬 여부를 지정해요. 기본값은 true, false를 넘기면 정렬을 끄지만 기반 파일시스템이 이미 정렬했을 수도 있어요.

    패턴(Patterns): 각 패턴 문자열은 특정 메타문자에 따라 확장돼요:

    • '*': 항목 이름의 어떤 부분 문자열과도 일치 (regexp /.*/mx와 비슷). 앞뒤 문자로 제한될 수 있음. Unix 숨김 항목명("dot file")은 일치하지 않아요. 포함하려면 IO::FNM_DOTMATCH 플래그나 '{*,.*}' 같은 걸 써요.
    • '**': 슬래시 '/'가 뒤따르면 재귀적으로 항목 이름과 일치. 다른 문자가 포함됐거나 슬래시가 뒤따르지 않으면 '*'와 동등.
    • '?': 단일 문자와 일치 (regexp /./와 비슷).
    • '[*set*]': 문자열 set의 한 문자와 일치. Regexp 문자 클래스처럼 동작 (부정 '[^a-z]' 포함).
    • '{*abc*,*xyz*}': 문자열 abc 또는 xyz와 일치. Regexp 교체(alternation)처럼 동작. 두 개 이상의 대안도 가능.
    • \: 뒤따르는 메타문자를 이스케이프. Windows에서는 문자열 패턴에 백슬래시를 못 쓸 수 있어요 (Dir['c:\foo*']는 안 되고 Dir['c:/foo*']를 쓰세요).

    예시 (단순 파일 트리 사용):

    File.basename(Dir.pwd) # => "example"
    Dir.glob('config.?')              # => ["config.h"]
    Dir.glob('*.[a-z][a-z]')          # => ["main.rb"]
    Dir.glob('*.{rb,h}')              # => ["main.rb", "config.h"]
    Dir.glob('*')                     # => ["config.h", "lib", "main.rb"]
    Dir.glob('*', File::FNM_DOTMATCH) # => [".", "config.h", "lib", "main.rb"]
    Dir.glob(["*.rb", "*.h"])         # => ["main.rb", "config.h"]
    
    Dir.glob('**/*.rb')
    => ["lib/song/karaoke.rb", "lib/song.rb", "main.rb"]
    

    플래그(Flags): 키워드 인자 flags가 주어지면(기본값은 0), 그 값은 모듈 File::Constants에 정의된 상수 중 하나 이상의 비트 OR이어야 해요. 적용되는 플래그:

    • File::FNM_DOTMATCH: '.'로 시작하는 항목 이름이 매칭에 고려되도록 지정.
    • File::FNM_EXTGLOB: 패턴 확장 '{*a*,*b*}'를 활성화 (regexp union처럼 동작).
    • File::FNM_NOESCAPE: 백슬래시 '\' 이스케이프 비활성화.
    • File::FNM_PATHNAME: '*''?' 메타문자가 디렉터리 구분자와 일치하지 않도록 지정.
    • File::FNM_SHORTNAME: 패턴이 존재한다면 짧은 이름과 일치할 수 있도록 지정. Windows 전용.
  • home(user_name = nil) → dirpathuser_namenil이 아니면 그 사용자의, 아니면 현재 로그인 사용자의 홈 디렉터리 경로를 돌려줘요: Dir.home # => "/home/me", Dir.home('root') # => "/root". user_name이 사용자 이름이 아니면 ArgumentError.

  • mkdir(dirpath, permissions = 0775) → 0 — 기반 파일시스템의 dirpath에 주어진 permissions로 디렉터리를 만들어요. permissions 인자는 Windows에서 무시돼요. Dir.mktmpdir(require 'tmpdir')는 임시 디렉터리를 만들어요.

  • new(dirpath) → dirdirpath 디렉터리에 대한 새 Dir 객체를 돌려줘요. 선택 키워드 인자 encoding은 디렉터리 항목 이름의 인코딩을 지정해요. nil(기본값)이면 파일시스템의 인코딩을 써요.

    Dir.new('.') # => #<Dir:.>
    
  • open(dirpath) → dirdirpath 디렉터리에 대한 새 Dir 객체를 만들어요. 블록 없이: Dir.new(dirpath, encoding)과 동등. 블록과 함께: 만들어진 dir로 블록을 호출하고, 블록 탈출 시 dir을 닫고 블록의 값을 돌려줘요.

    Dir.open('.') {|dir| dir.inspect } # => "#<Dir:.>"
    
  • pwd → string — 현재 작업 디렉터리 경로: Dir.chdir("/tmp") # => 0, Dir.pwd # => "/tmp"

  • rmdir(dirpath) → 0dirpath의 디렉터리를 제거해요. 비어 있지 않으면 예외.

  • tmpdir — 운영체제의 임시 파일 경로를 돌려줘요: require 'tmpdir'; Dir.tmpdir # => "/tmp"

인스턴스 메서드

  • chdir → 0 — 현재 작업 디렉터리를 self로 변경해요. 블록과 함께: 임시로 변경. 가능하면 Dir.fchdir, 아니면 Dir.chdir을 사용해요.

  • children → arrayself의 항목 이름 배열. '.''..' 제외: Dir.new('/example').children # => ["config.h", "lib", "main.rb"]

  • close → nilself의 스트림이 열려 있으면 닫고 nil을 돌려줘요. 이미 닫혀 있으면 무시.

  • each {|entry_name| ... } → selfself의 각 항목 이름으로 블록을 호출해요 (.·.. 포함). 블록이 없으면 Enumerator.

  • each_child {|entry_name| ... } → selfself의 각 항목 이름으로 블록을 호출해요 ('.'·'..' 제외). 블록이 없으면 enumerator.

  • fileno → integerdir에 쓰인 파일 디스크립터를 돌려줘요: d.fileno # => 8. dirfd() 함수 사용. 비-POSIX 플랫폼 미구현.

  • inspect → stringself의 문자열 설명: Dir.new('example').inspect # => "#<Dir:example>"

  • path → string or nilself를 만드는 데 쓰인 dirpath 문자열 (또는 Dir.for_fd로 만들었다면 nil): Dir.new('example').path # => "example"

  • pos = position → integerself의 위치를 설정하고 position을 돌려줘요. position은 이전 tell 호출에서 돌려받은 값이어야 해요.

  • read → string or nilself에서 다음 항목 이름을 읽고 돌려줘요. 스트림 끝이면 nil.

  • rewind → selfself의 위치를 0으로 설정해요.

  • seek(position) → selfself의 위치를 설정하고 self를 돌려줘요.

  • tell → integerself의 현재 위치를 돌려줘요.

출처: Ruby 4.0 API - Dir