FileUtils 모듈

FileUtils 모듈 (FileUtils)

FileUtils는 파일을 복사·이동·삭제하는 등의 파일 유틸리티 메서드를 담는 네임스페이스예요. File 클래스를 보완하지만 거기에 포함되거나 확장되지는 않아요. 대부분의 메서드가 셸 명령(cp, mv, rm, mkdir 등)의 동작을 Ruby로 옮겨 놓은 것이라서, verbose: true를 주면 실행할 것과 동등한 셸 명령을 출력해요.

출처: Ruby 4.0 API

본문

경로 인자 (Path Arguments)

여러 메서드가 경로 인자를 받아요. 문자열이면 그 값이 경로이고, :to_path 메서드가 있으면 그걸로, 없으면 :to_str로 변환돼요.

TOCTTOU 취약점 피하기 (Avoiding the TOCTTOU Vulnerability)

재귀적으로 항목을 제거하는 일부 메서드는 Time-of-check to time-of-use(TOCTTOU) 취약점에 노출될 수 있어요. 타깃 경로의 조상 디렉토리가 world-writable(/tmp 같은)이거나, 타깃 경로의 트리에 world-writable 하위 디렉토리나 심볼릭 링크가 포함된 경우예요.

이 취약점을 피하려면 FileUtils.remove_entry_secure를 쓰면 돼요. secure: true 키워드 인자를 받는 FileUtils.rm_r, FileUtils.rm_rf, 그리고 FileUtils.mv도 내부적으로 remove_entry_secure를 호출해요. 이 메서드는 특수한 사전 처리(대상 디렉토리의 소유자/권한을 고정하는 등)로 안전하게 제거해요. 대상 디렉토리의 소유자는 현재 프로세스나 root여야 하고, 모든 부모 디렉토리가 신뢰할 수 없는 사용자에 의해 옮겨질 수 없도록 보장해야 해요.

상수 (Constants)

  • VERSION — 버전 번호.

What's Here

FileUtils가 제공하는 메서드 분류는 이래요.

  • 생성: mkdir, mkdir_p(별칭 makedirs, mkpath), link_entry, ln(별칭 link), ln_s(별칭 symlink), ln_sf, ln_sr
  • 삭제: remove_dir, remove_entry, remove_entry_secure, remove_file, rm(별칭 remove), rm_f(별칭 safe_unlink), rm_r, rm_rf(별칭 rmtree), rmdir
  • 조회: pwd(별칭 getwd), uptodate?
  • 설정: cd(별칭 chdir), chmod, chmod_R, chown, chown_R, touch
  • 비교: compare_file(별칭 cmp, identical?), compare_stream
  • 복사: copy_entry, copy_file, copy_stream, cp(별칭 copy), cp_lr, cp_r, install
  • 이동: mv(별칭 move)
  • 옵션: collect_method, commands, have_option?, options, options_of

공통 키워드 인자로는 noop: true(실제로는 안 하고 건너뜀), verbose: true(동등 명령 출력)가 널리 쓰여요. force, preserve, secure, dereference_root, remove_destination 등은 메서드에 따라 달라요.

::cd / ::chdir (Public Class Method)

cd(dir, verbose: nil) { |dir| ... } (별칭 chdir) — 작업 디렉토리를 주어진 dir로 바꿔요. 블록이 없으면 현재 디렉토리를 바꾸고 0을 돌려줘요. 블록을 주면 블록 동안만 바꿨다가 다시 원래 디렉토리로 복원하고 블록의 값을 돌려줘요.

FileUtils.pwd                                     # => "/rdoc/fileutils"
FileUtils.cd('..') { |arg| [arg, FileUtils.pwd] } # => ["..", "/rdoc"]

::chmod / ::chmod_R (Public Class Method)

chmod(mode, list, noop: nil, verbose: nil)list의 경로(단일 또는 배열)에 있는 항목들의 권한을 mode로 바꿔요. 일반 파일은 File.chmod, 심볼릭 링크는 File.lchmod로 처리해요.

mode는 정수 또는 문자열일 수 있어요. 정수는 설정할 권한 비트예요. 문자열은 [targets][[operator][perms[,perms]] 형태로, targetsu(소유자)/g(그룹)/o(기타)/a(전체, 기본), operator+/-/=, permsr/w/x/X/s/t를 조합할 수 있어요.

FileUtils.chmod(0755, 'src0.txt')
FileUtils.chmod('u=wrx,go=rx', 'src1.txt')

chmod_R은 재귀적으로 권한을 바꿔요(force 키워드 추가).

::chown / ::chown_R (Public Class Method)

chown(user, group, list, noop: nil, verbose: nil)list의 경로에 있는 항목들의 소유자와 그룹을 바꿔요. 일반 파일은 File.chown, 심볼릭 링크는 File.lchown으로 처리해요. user/group은 이름 또는 id이고, nil이나 -1이면 그쪽은 바꾸지 않아요. chown_R은 재귀 버전이에요.

::collect_method (Public Class Method)

collect_method(opt) — 주어진 키워드 옵션 opt(심볼)를 받는 메서드들의 문자열 이름 배열을 돌려줘요.

FileUtils.collect_method(:preserve) # => ["cp", "copy", "cp_r", "install"]

::commands (Public Class Method)

commands() — 하나 이상의 키워드 인자를 받는 FileUtils 메서드들의 문자열 이름 배열을 돌려줘요.

FileUtils.commands.sort.take(3) # => ["cd", "chdir", "chmod"]

::compare_file / ::compare_stream (Public Class Method)

compare_file(a, b) (별칭 identical?, cmp) — 파일 ab의 내용이 동일하면 true. compare_stream(a, b) — 두 스트림의 내용이 동일하면 true.

::copy_entry / ::copy_file / ::copy_stream (Public Class Method)

copy_entry(src, dest, preserve = false, dereference_root = false, remove_destination = false)srcdest로 재귀적으로 복사해요. 일반 파일·디렉토리·심볼릭 링크의 파일 타입을 보존하며, FIFO나 디바이스 파일 등 다른 타입은 지원하지 않아요. dereference_root(기본 false)는 src가 심볼릭 링크면 그 링크를 따라가고, preserve(기본 false)는 파일 시간을 보존해요.

copy_file(src, dest, preserve = false, dereference = true) — 파일을 복사해요(디렉토리는 안 됨). copy_stream(src, dest)IO.copy_stream으로 스트림을 복사해요.

::cp / ::copy (Public Class Method)

cp(src, dest, preserve: nil, noop: nil, verbose: nil) (별칭 copy) — 파일을 복사해요. src가 파일이고 dest가 디렉토리가 아니면 srcdest로, dest가 디렉토리면 srcdest/src로 복사해요. src가 배열이고 dest가 디렉토리면 각각을 복사해요. src가 디렉토리면 예외를 발생시켜요.

FileUtils.touch('src0.txt')
FileUtils.cp('src0.txt', 'dest0.txt')
File.file?('dest0.txt') # => true

::cp_lr (Public Class Method)

cp_lr(src, dest, noop: nil, verbose: nil, dereference_root: true, remove_destination: false) — 하드 링크를 재귀적으로 만들어요. dest가 존재하는 파일/디렉토리인데 remove_destination: true를 주지 않으면 예외를 발생시켜요.

::cp_r (Public Class Method)

cp_r(src, dest, preserve: nil, noop: nil, verbose: nil, dereference_root: true, remove_destination: nil) — 파일을 재귀적으로 복사해요. 복사본에 mode, owner, group이 보존되는데, 그것들을 바꾸려면 FileUtils.install을 써요.

tree('src2')
# => src2
#    |-- dir0 ...
FileUtils.cp_r('src2', 'dest2')
tree('dest2')
# => dest2
#    |-- dir0 ...

src가 디렉토리인데 dest가 파일이면 예외를 발생시켜요.

::have_option? (Public Class Method)

have_option?(mid, opt) — 메서드 mid가 주어진 옵션 opt를 받으면 true, 아니면 false. 인자는 문자열 또는 심볼일 수 있어요.

FileUtils.have_option?(:chmod, :noop)  # => true
FileUtils.have_option?('chmod', 'secure') # => false

::install (Public Class Method)

install(src, dest, mode: nil, owner: nil, group: nil, preserve: nil, noop: nil, verbose: nil) — 파일 항목을 복사해요(셸의 install(1) 참고). 키워드 인자로 mode(권한), owner/group(소유자/그룹), preserve(타임스탬프 보존)를 지정할 수 있어요.

File.read('src0.txt')    # => "aaa\n"
FileUtils.install('src0.txt', 'dest0.txt')
File.read('dest0.txt')   # => "aaa\n"

::link_entry (Public Class Method)

link_entry(src, dest, dereference_root = false, remove_destination = false) — 하드 링크를 만들어요. src가 디렉토리면 그 안의 경로들을 가리키는 하드 링크를 재귀적으로 만들어요. dst가 존재하는데 remove_destination을 주지 않으면 예외를 발생시켜요. FileUtils.ln과는 옵션이 달라요.

ln(src, dest, force: nil, noop: nil, verbose: nil) (별칭 link) — 하드 링크를 만들어요. src가 파일이고 dest가 존재하지 않는 파일이면 destsrc를 가리키는 하드 링크를 만들고, dest가 디렉토리면 dest/src에 만들어요. force: truedest가 존재해도 덮어써요. dest가 존재하는 파일인데 forcetrue가 아니면 예외를 발생시켜요.

ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil) (별칭 symlink) — 심볼릭 링크를 만들어요. force: truedest가 존재해도 덮어써요. relative: truedest에 상대적인 링크를 만들어요(ln_sr 호출).

::ln_sf (Public Class Method)

ln_sf(src, dest, noop: nil, verbose: nil)FileUtils.ln_s와 같되 항상 force: true를 준 것처럼 동작해요.

::ln_sr (Public Class Method)

ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)FileUtils.ln_s와 같되 dest에 상대적인 링크를 만들어요.

::mkdir (Public Class Method)

mkdir(list, mode: nil, noop: nil, verbose: nil) — 주어진 경로들에 디렉토리를 만들어요. 내부적으로 Dir.mkdir(path, mode)를 호출해요. mode:를 주면 추가로 File.chmod(mode, path)도 호출해요. 어떤 경로가 존재하는 파일/디렉토리면 예외를 발생시켜요.

::mkdir_p / ::mkpath / ::makedirs (Public Class Method)

mkdir_p(list, mode: nil, noop: nil, verbose: nil) (별칭 mkpath, makedirs) — 주어진 경로들에 디렉토리를 만들되, 필요한 조상 디렉토리도 함께 만들어요(셸의 mkdir -p와 같은 동작).

FileUtils.mkdir_p(%w[tmp0/tmp1 tmp2/tmp3]) # => ["tmp0/tmp1", "tmp2/tmp3"]

::mv / ::move (Public Class Method)

mv(src, dest, force: nil, noop: nil, verbose: nil, secure: nil) (별칭 move) — 항목들을 이동해요. srcdest가 서로 다른 파일시스템에 있으면 먼저 복사한 뒤 src를 제거해요. secure: true를 주지 않고 다른 파일시스템 간 이동을 하면 로컬 취약점이 생길 수 있어요(TOCTTOU 섹션 참고). force: truesrc 제거 시 발생하는 StandardError 계열 예외를 무시해요.

::options (Public Class Method)

options() — 모든 키워드 이름의 문자열 배열을 돌려줘요.

FileUtils.options.take(3) # => ["noop", "verbose", "force"]

::options_of (Public Class Method)

options_of(mid) — 메서드 mid의 키워드 이름의 문자열 배열을 돌려줘요.

FileUtils.options_of(:rm)  # => ["force", "noop", "verbose"]
FileUtils.options_of('mv') # => ["force", "noop", "verbose", "secure"]

::pwd / ::getwd (Public Class Method)

pwd() (별칭 getwd) — 현재 디렉토리 경로를 담은 문자열을 돌려줘요.

::remove_dir (Public Class Method)

remove_dir(path, force = false)path의 디렉토리 항목을 재귀적으로 제거해요. force(기본 false)는 StandardError 계열 예외를 무시할지 지정해요.

::remove_entry (Public Class Method)

remove_entry(path, force = false)path의 항목(일반 파일, 심볼릭 링크, 디렉토리)을 제거해요. 디렉토리면 후손까지 제거해요.

::remove_entry_secure (Public Class Method)

remove_entry_secure(path, force = false)remove_entry와 같되 안전하게 제거해요. TOCTTOU 취약점을 피하는 사전 처리를 적용해요(대상 디렉토리와 그 후손들의 소유자·권한을 먼저 고정한 뒤 제거). 대상 디렉토리의 부모가 world-writable인데 sticky bit가 없으면 ArgumentError를 발생시켜요.

::remove_file (Public Class Method)

remove_file(path, force = false)path의 파일 항목(일반 파일 또는 심볼릭 링크)을 제거해요.

::rm / ::remove (Public Class Method)

rm(list, force: nil, noop: nil, verbose: nil) (별칭 remove) — 주어진 경로들에 있는 파일들을 제거해요. force: trueStandardError 계열 예외를 무시해요.

FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]

rm_f(list, noop: nil, verbose: nil) (별칭 safe_unlink) — FileUtils.rm(list, force: true, ...)와 동등해요. force: true로 호출한 것처럼 동작해요.

::rm_r (Public Class Method)

rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil) — 경로들의 항목을 제거하되, 디렉토리면 후손까지 재귀적으로 제거해요. secure: true를 주지 않으면 로컬 취약점이 생길 수 있어요.

::rm_rf / ::rmtree (Public Class Method)

rm_rf(list, noop: nil, verbose: nil, secure: nil) (별칭 rmtree) — FileUtils.rm_r(list, force: true, ...)와 동등해요.

::rmdir (Public Class Method)

rmdir(list, parents: nil, noop: nil, verbose: nil) — 주어진 경로들의 디렉토리를 제거해요. parents: true면 비어 있으면 연속된 조상 디렉토리도 제거해요. 디렉토리가 없거나 제거할 수 없으면 예외를 발생시켜요.

::touch (Public Class Method)

touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) — 주어진 경로들의 항목의 수정 시간(mtime)과 접근 시간(atime)을 갱신해요. 기본으로 존재하지 않는 경로에 빈 파일을 만들고, nocreate: true를 주면 대신 예외를 발생시켜요. mtime:으로 시간을 지정할 수 있어요.

FileUtils.touch('src0.txt')
FileUtils.touch(['src0.txt', 'src0.dat'])

::uptodate? (Public Class Method)

uptodate?(new, old_list) — 경로 new의 파일이 배열 old_list의 모든 파일보다 더 새롭고(최신) 시간이면 true, 아니면 false. 존재하지 않는 파일은 무한히 오래된 것으로 간주돼요.

FileUtils.uptodate?('Rakefile', ['Gemfile', 'README.md']) # => true
FileUtils.uptodate?('Gemfile', ['Rakefile', 'README.md']) # => false