Pathname 클래스
Pathname 클래스
Pathname은 파일시스템에 있는 파일이나 디렉터리의 이름을 나타내요. 파일 자체는 아니에요.
출처: Ruby 3.3 API
본문
Pathname은 운영체제에 따라 달라져요. Unix, Windows 등이죠. 이 라이브러리는 로컬 OS의 pathname과 함께 동작하지만, 비-Unix pathname도 실험적으로 지원해요.
Pathname은 상대 경로일 수도 있고 절대 경로일 수도 있어요. 파일이 실제로 존재하는지조차 파일을 참조하려고 할 때까지는 중요하지 않아요.
Pathname은 immutable이에요. 파괴적 갱신을 하는 메서드가 없어요.
이 클래스의 목표는 표준 Ruby가 제공하는 것보다 더 깔끔한 방식으로 파일 경로 정보를 다루는 거예요. 아래 예시들이 그 차이를 보여 줘요.
File, FileTest의 모든 기능과 Dir, FileUtils의 일부 기능이 자연스럽게 포함돼 있어요. 기본적으로 이 모든 것(그 이상)의 파사드(facade)예요.
예시 (Examples)
예시 1: Pathname 사용하기
require 'pathname'
pn = Pathname.new("/usr/bin/ruby")
size = pn.size # 27662
isdir = pn.directory? # false
dir = pn.dirname # Pathname:/usr/bin
base = pn.basename # Pathname:ruby
dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby]
data = pn.read
pn.open { |f| _ }
pn.each_line { |line| _ }
예시 2: 표준 Ruby 사용하기
pn = "/usr/bin/ruby"
size = File.size(pn) # 27662
isdir = File.directory?(pn) # false
dir = File.dirname(pn) # "/usr/bin"
base = File.basename(pn) # "ruby"
dir, base = File.split(pn) # ["/usr/bin", "ruby"]
data = File.read(pn)
File.open(pn) { |f| _ }
File.foreach(pn) { |line| _ }
예시 3: 특별한 기능
p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib
p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8
p3 = p1.parent # Pathname:/usr
p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8
pwd = Pathname.pwd # Pathname:/home/gavin
pwd.absolute? # true
p5 = Pathname.new "." # Pathname:.
p5 = p5 + "music/../articles" # Pathname:music/../articles
p5.cleanpath # Pathname:articles
p5.realpath # Pathname:/home/gavin/articles
p5.children # [Pathname:/home/gavin/articles/linux, ...]
기능 분해 (Breakdown of functionality)
핵심 메서드 (Core methods)
이 메서드들은 사실상 String을 다루는 거예요. 경로가 그게 전부니까요. mountpoint?, children, each_child, realdirpath, realpath를 제외하면 어느 것도 파일시스템에 접근하지 않아요.
+, join, parent, root?, absolute?, relative?, relative_path_from, each_filename, cleanpath, realpath, realdirpath, children, each_child, mountpoint?
파일 상태 프레디킷 메서드 (File status predicate methods)
FileTest의 파사드예요: blockdev?, chardev?, directory?, executable?, executable_real?, exist?, file?, grpowned?, owned?, pipe?, readable?, world_readable?, readable_real?, setgid?, setuid?, size, size?, socket?, sticky?, symlink?, writable?, world_writable?, writable_real?, zero?
파일 속성·조작 메서드 (File property and manipulation methods)
File의 파사드예요: atime, birthtime, ctime, mtime, chmod(mode), lchmod(mode), chown(owner, group), lchown(owner, group), fnmatch(pattern, *args), fnmatch?(pattern, *args), ftype, make_link(old), open(*args, &block), readlink, rename(to), stat, lstat, make_symlink(old), truncate(length), utime(atime, mtime), lutime(atime, mtime), basename(*args), dirname, extname, expand_path(*args), split
디렉터리 메서드 (Directory methods)
Dir의 파사드예요: Pathname.glob(*args), Pathname.getwd / Pathname.pwd, rmdir, entries, each_entry(&block), mkdir(*args), opendir(*args)
IO
IO의 파사드예요: each_line(*args, &block), read(*args), binread(*args), readlines(*args), sysopen(*args), write(*args), binwrite(*args)
유틸리티 (Utilities)
Find, FileUtils 등의 혼합이에요: find(&block), mkpath, rmtree, unlink / delete
메서드 문서 (Method documentation)
위 섹션에서 봤듯이 Pathname의 대부분 메서드는 파사드예요. 이 메서드들의 문서는 대체로 "See FileTest.writable?"처럼 원본 메서드에 익숙하다는 전제 하에 짧게 돼 있어요. 원본 메서드 문서(ri 등을 통해)에는 더 많은 정보가 있을 거예요.
상수 (Constants)
- VERSION
Public Class Methods
getwd ()
현재 작업 디렉터리를 Pathname으로 반환해요.
Pathname.getwd
#=> #<Pathname:/home/zzak/projects/ruby>
Dir.getwd 참고.
glob (p1, p2 = v2, p3 = v3)
Pathname 객체를 반환하거나 넘겨줘요.
Pathname.glob("lib/i*.rb")
#=> [#<Pathname:lib/ipaddr.rb>, #<Pathname:lib/irb.rb>]
Dir.glob 참고.
new (p1)
주어진 String(또는 String 같은 객체)에서 Pathname 객체를 만들어요. path에 NULL 문자(\0)가 있으면 ArgumentError가 던져져요.
pwd ()
현재 작업 디렉터리를 Pathname으로 반환해요.
Pathname.getwd
#=> #<Pathname:/home/zzak/projects/ruby>
Dir.getwd 참고.
Public Instance Methods
+ (other)
pathname 조각을 self에 이어붙여 새 Pathname 객체를 만들어요. other가 self에 대한 상대 경로로 간주되므로, other가 절대 경로면 새 Pathname 객체는 other만으로 만들어져요.
p1 = Pathname.new("/usr") # Pathname:/usr
p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
# / is aliased to +.
p4 = p1 / "bin/ruby" # Pathname:/usr/bin/ruby
p5 = p1 / "/etc/passwd" # Pathname:/etc/passwd
이 메서드는 파일시스템에 접근하지 않아요. 순수한 문자열 조작이에요.
/ (other)
+의 별칭이에요.
<=> (p1)
pathname을 위한 대소문자 구분 비교 연산자예요.
Pathname.new('/usr') <=> Pathname.new('/usr/bin')
#=> -1
Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin')
#=> 0
Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN')
#=> 1
왼쪽 인자가 오른쪽 인자에 비해 어느 쪽인지에 따라 -1, 0, 1을 반환해요. 비교할 수 없으면 nil을 반환해요.
== (p1), === (p1), eql? (p1)
이 pathname을 other와 비교해요. 비교는 문자열 기반이에요. 두 개의 서로 다른 경로(foo.txt와 ./foo.txt)가 같은 파일을 가리킬 수 있다는 점을 유의해요.
absolute? ()
경로가 절대 경로인지 테스트하는 프레디킷 메서드예요.
pathname이 슬래시로 시작하면 true를 반환해요.
p = Pathname.new('/im/sure')
p.absolute?
#=> true
p = Pathname.new('not/so/sure')
p.absolute?
#=> false
ascend () { |self| ... }
주어진 경로의 각 요소에 대해 오름차순으로 새 Pathname 객체를 반복해서 넘겨줘요.
Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
#<Pathname:/path/to/some/file.rb>
#<Pathname:/path/to/some>
#<Pathname:/path/to>
#<Pathname:/path>
#<Pathname:/>
Pathname.new('path/to/some/file.rb').ascend {|v| p v}
#<Pathname:path/to/some/file.rb>
#<Pathname:path/to/some>
#<Pathname:path/to>
#<Pathname:path>
블록이 없으면 Enumerator를 반환해요.
enum = Pathname.new("/usr/bin/ruby").ascend
# ... do stuff ...
enum.each { |e| ... }
# yields Pathnames /usr/bin/ruby, /usr/bin, /usr, and /.
파일시스템에는 접근하지 않아요.
atime → time
파일의 마지막 접근 시간을 반환해요.
File.atime 참고.
basename (p1 = v1)
경로의 마지막 구성요소를 반환해요.
File.basename 참고.
binread([length [, offset]]) → string
파일의 모든 바이트를 반환하고, 지정하면 첫 N개를 반환해요.
File.binread 참고.
binwrite(string, [offset]) → fixnum
바이너리 모드로 파일을 열어 contents를 써요.
File.binwrite 참고.
birthtime → time
파일의 birth time을 반환해요. 플랫폼이 birthtime을 지원하지 않으면 NotImplementedError를 던져요.
File.birthtime 참고.
blockdev? / chardev? / directory? / executable? / executable_real? / exist? / file? / grpowned? / owned? / pipe? / readable? / readable_real? / setgid? / setuid? / size / size? / socket? / sticky? / symlink? / world_readable? / world_writable? / writable? / writable_real? / zero?
각각 FileTest.X를 참고해요.
children (with_directory=true)
디렉터리의 자식들(파일과 하위디렉터리, 재귀 아님)을 Pathname 객체 배열로 반환해요.
기본적으로 반환되는 pathname은 파일에 접근하기에 충분한 정보를 가져요. with_directory를 false로 설정하면 파일 이름만 담긴 pathname이 반환돼요.
pn = Pathname("/usr/lib/ruby/1.8")
pn.children
# -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
Pathname:/usr/lib/ruby/1.8/Env.rb,
Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
pn.children(false)
# -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
결과에는 디렉터리의 .과 ..이 절대 포함되지 않아요. 그것들은 자식이 아니니까요.
chmod(mode_int) → integer
파일 권한을 바꿔요.
File.chmod 참고.
chown(owner_int, group_int) → integer
파일의 소유자와 그룹을 바꿔요.
File.chown 참고.
cleanpath (consider_symlink=false)
self의 깨끗한 pathname을 반환해요. 연속 슬래시와 쓸모없는 점이 제거돼요. 파일시스템에는 접근하지 않아요.
consider_symlink가 true면 심볼릭 링크를 깨뜨리지 않는 더 보수적인 알고리즘이 사용돼요. 필요 이상으로 .. 엔트리를 더 많이 유지할 수 있지만, 파일시스템에 접근하지 않고는 피할 수 없어요.
Pathname#realpath 참고.
ctime → time
파일 자체가 아니라 디렉터리 정보를 사용해 마지막 변경 시간을 반환해요.
File.ctime 참고.
delete () / unlink ()
self가 파일이면 File.unlink, 그렇지 않으면 Dir.unlink을 사용해 파일이나 디렉터리를 제거해요.
descend () { |v| ... }
주어진 경로의 각 요소에 대해 내림차순으로 새 Pathname 객체를 반복해서 넘겨줘요.
Pathname.new('/path/to/some/file.rb').descend {|v| p v}
#<Pathname:/>
#<Pathname:/path>
#<Pathname:/path/to>
#<Pathname:/path/to/some>
#<Pathname:/path/to/some/file.rb>
Pathname.new('path/to/some/file.rb').descend {|v| p v}
#<Pathname:path>
#<Pathname:path/to>
#<Pathname:path/to/some>
#<Pathname:path/to/some/file.rb>
블록이 없으면 Enumerator를 반환해요.
enum = Pathname.new("/usr/bin/ruby").descend
# ... do stuff ...
enum.each { |e| ... }
# yields Pathnames /, /usr, /usr/bin, and /usr/bin/ruby.
파일시스템에는 접근하지 않아요.
dirname ()
경로의 마지막 구성요소를 뺀 나머지를 반환해요.
File.dirname 참고.
each_child (with_directory=true, &b)
디렉터리의 자식들(파일과 하위디렉터리, 재귀 아님)을 반복해요.
각 자식에 대해 Pathname 객체를 넘겨줘요.
기본적으로 넘겨지는 pathname은 파일에 접근하기에 충분한 정보를 가져요. with_directory를 false로 설정하면 파일 이름만 담긴 pathname이 반환돼요.
Pathname("/usr/local").each_child {|f| p f }
#=> #<Pathname:/usr/local/share>
# #<Pathname:/usr/local/bin>
# #<Pathname:/usr/local/games>
# #<Pathname:/usr/local/lib>
# #<Pathname:/usr/local/include>
# #<Pathname:/usr/local/sbin>
# #<Pathname:/usr/local/src>
# #<Pathname:/usr/local/man>
Pathname("/usr/local").each_child(false) {|f| p f }
#=> #<Pathname:share>
# #<Pathname:bin>
# #<Pathname:games>
# #<Pathname:lib>
# #<Pathname:include>
# #<Pathname:sbin>
# #<Pathname:src>
# #<Pathname:man>
결과에는 .과 ..이 절대 포함되지 않아요. Pathname#children 참고.
each_entry ()
디렉터리의 엔트리(파일과 하위디렉터리)를 반복하며 각 엔트리에 대해 Pathname 객체를 넘겨줘요.
each_filename () { |filename| ... }
경로의 각 구성요소를 반복해요.
Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
# yields "usr", "bin", and "ruby".
블록이 없으면 Enumerator를 반환해요.
enum = Pathname.new("/usr/bin/ruby").each_filename
# ... do stuff ...
enum.each { |e| ... }
# yields "usr", "bin", and "ruby".
each_line {|line| ... }
파일의 각 줄을 반복하며 각 줄에 대해 String 객체를 넘겨줘요.
empty? ()
파일이 비어 있는지 테스트해요.
Dir#empty?와 FileTest.empty? 참고.
entries ()
디렉터리의 엔트리(파일과 하위디렉터리)를 각각 Pathname 객체로 반환해요.
결과에는 디렉터리 안의 이름만 담겨요. 뒤에 붙는 슬래시나 재귀 탐색은 없어요.
pp Pathname.new('/usr/local').entries
#=> [#<Pathname:share>,
# #<Pathname:lib>,
# #<Pathname:..>,
# #<Pathname:include>,
# #<Pathname:etc>,
# #<Pathname:bin>,
# #<Pathname:man>,
# #<Pathname:games>,
# #<Pathname:.>,
# #<Pathname:sbin>,
# #<Pathname:src>]
결과에는 현재 디렉터리 #<Pathname:.>과 부모 디렉터리 #<Pathname:..>이 포함될 수 있어요. .과 ..을 원하지 않고 디렉터리를 원한다면 Pathname#children을 고려해 보세요.
expand_path (p1 = v1)
파일의 절대 경로를 반환해요.
File.expand_path 참고.
extname ()
파일의 확장자를 반환해요.
File.extname 참고.
file? ()
FileTest.file? 참고.
find (ignore_error: true) { |pathname| ... }
디렉터리 트리를 깊이 우선으로 반복하며 "이" 디렉터리 아래 각 파일에 대해 Pathname을 넘겨줘요.
블록이 없으면 Enumerator를 반환해요.
표준 라이브러리 모듈 Find로 구현되므로, Find.prune으로 탐색을 제어할 수 있어요.
self가 .이면 넘겨지는 pathname은 ./가 아니라 현재 디렉터리의 파일 이름으로 시작해요.
Find.find 참고.
fnmatch(pattern, [flags]) → true or false, fnmatch?(pattern, [flags]) → true or false
수신자가 주어진 패턴과 일치하면 true를 반환해요.
File.fnmatch 참고.
freeze → obj
이 Pathname을 동결해요.
Object.freeze 참고.
ftype → string
파일의 "type"("file", "directory" 등)을 반환해요.
File.ftype 참고.
glob (p1, p2 = v2)
Pathname 객체를 반환하거나 넘겨줘요.
Pathname("ruby-2.4.2").glob("R*.md")
#=> [#<Pathname:ruby-2.4.2/README.md>, #<Pathname:ruby-2.4.2/README.ja.md>]
Dir.glob 참고. 이 메서드는 Dir.glob의 base 키워드 인자를 사용해요.
join (*args)
주어진 pathname들을 self에 이어붙여 새 Pathname 객체를 만들어요. 이는 Pathname#+로 self와 모든 인자를 순차적으로 이어붙이는 것과 사실상 같아요.
path0 = Pathname.new("/usr") # Pathname:/usr
path0 = path0.join("bin/ruby") # Pathname:/usr/bin/ruby
# is the same as
path1 = Pathname.new("/usr") + "bin/ruby" # Pathname:/usr/bin/ruby
path0 == path1
#=> true
lchmod(mode_int) → integer
Pathname.chmod와 같지만 심볼릭 링크를 따라가지 않아요.
File.lchmod 참고.
lchown(owner_int, group_int) → integer
Pathname.chown와 같지만 심볼릭 링크를 따라가지 않아요.
File.lchown 참고.
lstat ()
File.lstat 참고.
lutime (p1, p2)
파일의 접근·수정 시간을 갱신해요. Pathname#utime과 같지만 심볼릭 링크를 따라가지 않아요.
File.lutime 참고.
make_link(old)
pathname에 하드 링크를 만들어요.
File.link 참고.
make_symlink(old)
심볼릭 링크를 만들어요.
File.symlink 참고.
mkdir (p1 = v1)
참조하는 디렉터리를 만들어요.
Dir.mkdir 참고.
mkpath (mode: nil)
아직 존재하지 않는 중간 디렉터리를 포함해 전체 경로를 만들어요.
FileUtils.mkpath와 FileUtils.mkdir_p 참고.
mountpoint? ()
self가 마운트포인트를 가리키면 true를 반환해요.
mtime → time
파일의 마지막 수정 시간을 반환해요.
File.mtime 참고.
open()
읽기나 쓰기를 위해 파일을 열어요.
File.open 참고.
opendir ()
참조하는 디렉터리를 열어요.
Dir.open 참고.
owned? ()
FileTest.owned? 참고.
parent ()
부모 디렉터리를 반환해요. self + '..'과 같아요.
pipe? ()
FileTest.pipe? 참고.
read([length [, offset]]) → string
파일의 모든 데이터를 반환하고, 지정하면 첫 N바이트를 반환해요.
File.read 참고.
readable? / readable_real? ()
FileTest.readable? / FileTest.readable_real? 참고.
readlines(sep=$/ [, open_args]) → array
파일의 모든 줄을 반환해요.
File.readlines 참고.
readlink ()
심볼릭 링크를 읽어요.
File.readlink 참고.
realdirpath (p1 = v1)
실제 파일시스템에서 self의 실제(절대) pathname을 반환해요.
심볼릭 링크나 쓸모없는 점 .., .을 담지 않아요.
실제 pathname의 마지막 구성요소는 존재하지 않을 수 있어요.
realpath (p1 = v1)
실제 파일시스템에서 self의 실제(절대) pathname을 반환해요.
심볼릭 링크나 쓸모없는 점 .., .을 담지 않아요.
이 메서드를 호출할 때는 pathname의 모든 구성요소가 존재해야 해요.
relative? ()
Pathname#absolute?의 반대예요.
pathname이 슬래시로 시작하면 false를 반환해요.
p = Pathname.new('/im/sure')
p.relative?
#=> false
p = Pathname.new('not/so/sure')
p.relative?
#=> true
relative_path_from (base_directory)
주어진 base_directory에서 수신자까지의 상대 경로를 반환해요.
self가 절대 경로면 base_directory도 절대 경로여야 해요. self가 상대 경로면 base_directory도 상대 경로여야 해요.
이 메서드는 파일시스템에 접근하지 않아요. 심볼릭 링크가 없다고 가정해요.
상대 경로를 찾지 못하면 ArgumentError가 던져져요.
이 메서드는 사용 중인 파일시스템의 대소문자 구분이 운영체제 기본값과 다른 경우를 처리하지 않는다는 점을 참고해요.
rename (p1)
파일의 이름을 바꿔요.
File.rename 참고.
rmdir ()
참조하는 디렉터리를 제거해요.
Dir.rmdir 참고.
rmtree (noop: nil, verbose: nil, secure: nil)
아래에 있는 모든 디렉터리를 포함해 디렉터리를 재귀적으로 삭제해요.
FileUtils.rm_rf 참고.
root? ()
루트 디렉터리용 프레디킷 메서드예요. pathname이 연속 슬래시로 구성돼 있으면 true를 반환해요.
파일시스템에는 접근하지 않아요. 그래서 /usr/..처럼 루트를 가리키는 일부 pathname에 대해 false를 반환할 수 있어요.
size () / size? ()
FileTest.size / FileTest.size? 참고.
split ()
dirname과 basename을 배열로 반환해요.
File.split 참고.
stat ()
File::Stat 객체를 반환해요.
File.stat 참고.
sticky? ()
FileTest.sticky? 참고.
sub (*args)
String#sub로 치환된 pathname을 반환해요.
path1 = Pathname.new('/usr/bin/perl')
path1.sub('perl', 'ruby')
#=> #<Pathname:/usr/bin/ruby>
sub_ext (p1)
basename에 repl을 접미사로 추가한 pathname을 반환해요.
self에 확장자 부분이 없으면 repl이 붙여져요.
Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
#=> #<Pathname:/usr/bin/shutdown.rb>
sysopen([mode, [perm]]) → fixnum
IO.sysopen 참고.
to_path → string, to_s → string
경로를 String으로 반환해요.
to_path는 Pathname 객체가 File.open 등에서 쓸 수 있도록 구현돼 있어요.
truncate (p1)
파일을 length바이트로 잘라요.
File.truncate 참고.
utime (p1, p2)
파일의 접근·수정 시간을 갱신해요.
File.utime 참고.
write(string, [offset]) → fixnum
contents를 파일에 써요.
File.write 참고.