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]] 형태로, targets는 u(소유자)/g(그룹)/o(기타)/a(전체, 기본), operator는 +/-/=, perms는 r/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) — 파일 a와 b의 내용이 동일하면 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) — src를 dest로 재귀적으로 복사해요. 일반 파일·디렉토리·심볼릭 링크의 파일 타입을 보존하며, 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가 디렉토리가 아니면 src를 dest로, dest가 디렉토리면 src를 dest/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 / ::link (Public Class Method)
ln(src, dest, force: nil, noop: nil, verbose: nil) (별칭 link) — 하드 링크를 만들어요. src가 파일이고 dest가 존재하지 않는 파일이면 dest에 src를 가리키는 하드 링크를 만들고, dest가 디렉토리면 dest/src에 만들어요. force: true면 dest가 존재해도 덮어써요. dest가 존재하는 파일인데 force가 true가 아니면 예외를 발생시켜요.
::ln_s / ::symlink (Public Class Method)
ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil) (별칭 symlink) — 심볼릭 링크를 만들어요. force: true면 dest가 존재해도 덮어써요. relative: true면 dest에 상대적인 링크를 만들어요(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) — 항목들을 이동해요. src와 dest가 서로 다른 파일시스템에 있으면 먼저 복사한 뒤 src를 제거해요. secure: true를 주지 않고 다른 파일시스템 간 이동을 하면 로컬 취약점이 생길 수 있어요(TOCTTOU 섹션 참고). force: true는 src 제거 시 발생하는 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: true는 StandardError 계열 예외를 무시해요.
FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
::rm_f / ::safe_unlink (Public Class Method)
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