Class: Pathname
- Defined in:
- lib/pleasant_path/pathname.rb,
lib/pleasant_path/json/pathname.rb,
lib/pleasant_path/yaml/pathname.rb
Constant Summary collapse
- NULL =
File::NULLas a Pathname. On POSIX systems, this should be equivalent to Pathname.new(“/dev/null”). Pathname.new(File::NULL)
Instance Method Summary collapse
-
#^(sibling) ⇒ Pathname
Joins the Pathname
dirnamewith the givensibling. -
#append_file(source) ⇒ self
Appends the contents of file indicated by
sourceto the file indicated by the Pathname. -
#append_lines(lines, eol: $/) ⇒ self
Appends each object in
linesas a string plus end-of-line (EOL) characters to the file indicated by the Pathname. -
#append_text(text) ⇒ self
Appends
textto the file indicated by the Pathname. -
#available_name(format = "%{name}_%{i}%{ext}", i: 1) ⇒ Pathname
Finds an available name based on the Pathname.
-
#chdir ⇒ Object
Changes the current working directory to the Pathname.
-
#common_path(other) ⇒ Pathname
Returns the longest path that the Pathname and
otherhave in common. -
#copy(destination) ⇒ Pathname
Copies the file or directory indicated by the Pathname to
destination, in the same manner asFileUtils.cp_r. -
#copy_as(destination) ⇒ Object
Copies the file or directory indicated by the Pathname to a destination, replacing any existing file or directory.
-
#copy_into(directory, &block) ⇒ Object
Copies the file or directory indicated by the Pathname into
directory, replacing any existing file or directory of the same basename. -
#delete! ⇒ self
Recursively deletes the directory or file indicated by the Pathname.
-
#dirs ⇒ Array<Pathname>
Returns the immediate child directories of the directory indicated by the Pathname.
-
#dirs_r ⇒ Array<Pathname>
Returns all (recursive) descendent directories of the directory indicated by the Pathname.
-
#edit_lines(eol: $/) {|lines| ... } ⇒ Array<String>
Reads the entire contents of the file indicated by the Pathname as an array of lines, and yields that array to the given block for editing.
-
#edit_text {|text| ... } ⇒ String
Reads the entire contents of the file indicated by the Pathname as a string, and yields that string to the given block for editing.
-
#existence ⇒ self?
Returns the Pathname if
exist?returns true, otherwise returns nil. -
#files ⇒ Array<Pathname>
Returns the immediate child files of the directory indicated by the Pathname.
-
#files_r ⇒ Array<Pathname>
Returns all (recursive) descendent files of the directory indicated by the Pathname.
-
#find_dirs ⇒ Object
Iterates over all (recursive) descendent directories of the directory indicated by the Pathname.
-
#find_files ⇒ Object
Iterates over all (recursive) descendent files of the directory indicated by the Pathname.
-
#load_json(options = {}) ⇒ Object
Parses the contents of the file indicated by the Pathname as JSON, deserializing arbitrary data types via type information embedded in the JSON.
-
#load_yaml ⇒ Object
Parses the contents of the file indicated by the Pathname as YAML, deserializing arbitrary data types via type information embedded in the YAML.
-
#make_dir ⇒ self
Creates the directory indicated by the Pathname, including any necessary parent directories.
-
#make_dirname ⇒ self
Creates the directory indicated by the Pathname
dirname, including any necessary parent directories. -
#make_file ⇒ Pathname
Creates the file indicated by the Pathname, including any necessary parent directories.
-
#move(destination) ⇒ Pathname
Moves the file or directory indicated by the Pathname to
destination, in the same manner asFileUtils.mv. -
#move_as(destination) ⇒ Object
(also: #rename_as)
Moves the file or directory indicated by the Pathname to a destination, replacing any existing file or directory.
-
#move_into(directory, &block) ⇒ Object
Moves the file or directory indicated by the Pathname into
directory, replacing any existing file or directory of the same basename. -
#parentname ⇒ Pathname
Returns the
basenameof the parent directory (dirname). -
#read_json(options = {}) ⇒ nil, ...
Parses the contents of the file indicated by the Pathname as JSON.
-
#read_lines(eol: $/) ⇒ Array<String>
Reads all lines from the file indicated by the Pathname, and returns them with all end-of-line (EOL) characters stripped.
-
#read_yaml ⇒ nil, ...
Parses the contents of the file indicated by the Pathname as YAML.
-
#rename_basename(new_basename, &block) ⇒ Object
Renames the file or directory indicated by the Pathname relative to its
dirname, replacing any existing file or directory of the same basename. -
#rename_extname(new_extname, &block) ⇒ Object
Changes the file extension (
extname) of the file indicated by the Pathname, replacing any existing file or directory of the same resultant basename. -
#to_pathname ⇒ self
Returns the Pathname unmodified.
-
#touch_file ⇒ self
deprecated
Deprecated.
Use #make_file.
-
#write_lines(lines, eol: $/) ⇒ self
Writes each object in
linesas a string plus end-of-line (EOL) characters to the file indicated by the Pathname, overwriting the file if it exists. -
#write_text(text) ⇒ self
Writes
textto the file indicated by the Pathname, overwriting the file if it exists.
Instance Method Details
#^(sibling) ⇒ Pathname
Joins the Pathname dirname with the given sibling.
The mnemonic for this operator is that the result is formed by going up one directory level from the original path, then going back down to sibling.
29 30 31 |
# File 'lib/pleasant_path/pathname.rb', line 29 def ^(sibling) self.dirname / sibling end |
#append_file(source) ⇒ self
Appends the contents of file indicated by source to the file indicated by the Pathname. Returns the Pathname.
1151 1152 1153 1154 |
# File 'lib/pleasant_path/pathname.rb', line 1151 def append_file(source) self.open("a"){|destination| IO::copy_stream(source, destination) } self end |
#append_lines(lines, eol: $/) ⇒ self
Appends each object in lines as a string plus end-of-line (EOL) characters to the file indicated by the Pathname. Creates the file if it does not exist, including any necessary parent directories. Returns the Pathname.
1056 1057 1058 1059 |
# File 'lib/pleasant_path/pathname.rb', line 1056 def append_lines(lines, eol: $/) self.make_dirname.open("a"){|f| f.write_lines(lines, eol: eol) } self end |
#append_text(text) ⇒ self
Appends text to the file indicated by the Pathname. Creates the file if it does not exist, including any necessary parent directories. Returns the Pathname.
1014 1015 1016 1017 |
# File 'lib/pleasant_path/pathname.rb', line 1014 def append_text(text) self.make_dirname.open("a"){|f| f.write(text) } self end |
#available_name(format = "%{name}_%{i}%{ext}", i: 1) ⇒ Pathname
Finds an available name based on the Pathname. If the Pathname does not point to an existing file or directory, returns the Pathname. Otherwise, iteratively generates and tests names until one is found that does not point to an existing file or directory.
Names are generated using a Hash-style format string with three populated values:
-
%{name}: original Pathname basename without extname
-
%{ext}: original Pathname extname, including leading dot
-
%{i}: iteration counter; can be initialized via
:ikwarg
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
# File 'lib/pleasant_path/pathname.rb', line 432 def available_name(format = "%{name}_%{i}%{ext}", i: 1) return self unless self.exist? dirname = File.dirname(self) format = "%{dirname}/" + format unless dirname == "." values = { dirname: dirname, name: File.basename(self, ".*"), ext: self.extname, i: i, } while (path = format % values) && File.exist?(path) values[:i] += 1 end path.to_pathname end |
#chdir ⇒ Pathname #chdir {|working_dir| ... } ⇒ retval
Changes the current working directory to the Pathname. If no block is given, this method returns the Pathname. Otherwise, the block is called with the Pathname, the original working directory is restored after the block exits, this method returns the return value of the block.
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/pleasant_path/pathname.rb', line 271 def chdir if block_given? Dir.chdir(self) do |dir| yield dir.to_pathname end else Dir.chdir(self) self end end |
#common_path(other) ⇒ Pathname
Returns the longest path that the Pathname and other have in common.
78 79 80 |
# File 'lib/pleasant_path/pathname.rb', line 78 def common_path(other) File.common_path([self.to_s, other.to_s]).to_pathname end |
#copy(destination) ⇒ Pathname
Copies the file or directory indicated by the Pathname to destination, in the same manner as FileUtils.cp_r. Creates any necessary parent directories of the destination. Returns destination as a Pathname.
668 669 670 671 672 673 |
# File 'lib/pleasant_path/pathname.rb', line 668 def copy(destination) destination = destination.to_pathname destination.make_dirname FileUtils.cp_r(self, destination) destination end |
#copy_as(destination) ⇒ Pathname #copy_as(destination) {|source, destination| ... } ⇒ Pathname
Copies the file or directory indicated by the Pathname to a destination, replacing any existing file or directory.
If a block is given and a file or directory does exist at the destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the copy is aborted.
Creates any necessary parent directories of the destination. Returns the destination as a Pathname (or the source Pathname in the case that the copy is aborted).
WARNING: Due to system API limitations, the copy is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is copied to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 |
# File 'lib/pleasant_path/pathname.rb', line 753 def copy_as(destination) destination = destination.to_pathname if block_given? && destination.exist? && self.exist? && !File.identical?(self, destination) destination = yield self, destination destination = nil if destination == self end if destination destination.delete! unless File.identical?(self, destination) self.copy(destination) end destination || self end |
#copy_into(directory) ⇒ Pathname #copy_into(directory) {|source, destination| ... } ⇒ Pathname
Copies the file or directory indicated by the Pathname into directory, replacing any existing file or directory of the same basename.
If a block is given and a file or directory does exist at the resultant destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the copy is aborted.
Creates any necessary parent directories of the destination. Returns the destination as a Pathname (or the source Pathname in the case that the copy is aborted).
WARNING: Due to system API limitations, the copy is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is copied to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.
827 828 829 |
# File 'lib/pleasant_path/pathname.rb', line 827 def copy_into(directory, &block) self.copy_as(directory / self.basename, &block) end |
#delete! ⇒ self
Recursively deletes the directory or file indicated by the Pathname. Similar to Pathname#rmtree, but does not raise an exception if the file does not exist. Returns the Pathname.
387 388 389 390 |
# File 'lib/pleasant_path/pathname.rb', line 387 def delete! self.rmtree if self.exist? self end |
#dirs ⇒ Array<Pathname>
Returns the immediate child directories of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname.
114 115 116 |
# File 'lib/pleasant_path/pathname.rb', line 114 def dirs self.children.tap{|c| c.select!(&:dir?) } end |
#dirs_r ⇒ Array<Pathname>
Returns all (recursive) descendent directories of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname, and are in depth-first order.
137 138 139 |
# File 'lib/pleasant_path/pathname.rb', line 137 def dirs_r self.find_dirs.to_a end |
#edit_lines(eol: $/) {|lines| ... } ⇒ Array<String>
Reads the entire contents of the file indicated by the Pathname as an array of lines, and yields that array to the given block for editing. Writes the return value of the block back to the file, overwriting previous contents. End-of-line (EOL) characters are stripped when reading, and appended after each line when writing. Returns the return value of the block.
1133 1134 1135 |
# File 'lib/pleasant_path/pathname.rb', line 1133 def edit_lines(eol: $/, &block) File.edit_lines(self, eol: eol, &block) end |
#edit_text {|text| ... } ⇒ String
Reads the entire contents of the file indicated by the Pathname as a string, and yields that string to the given block for editing. Writes the return value of the block back to the file, overwriting previous contents. Returns the return value of the block.
1107 1108 1109 |
# File 'lib/pleasant_path/pathname.rb', line 1107 def edit_text(&block) File.edit_text(self, &block) end |
#existence ⇒ self?
Returns the Pathname if exist? returns true, otherwise returns nil.
55 56 57 |
# File 'lib/pleasant_path/pathname.rb', line 55 def existence self if self.exist? end |
#files ⇒ Array<Pathname>
Returns the immediate child files of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname.
190 191 192 |
# File 'lib/pleasant_path/pathname.rb', line 190 def files self.children.tap{|c| c.select!(&:file?) } end |
#files_r ⇒ Array<Pathname>
Returns all (recursive) descendent files of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname, and are in depth-first order.
213 214 215 |
# File 'lib/pleasant_path/pathname.rb', line 213 def files_r self.find_files.to_a end |
#find_dirs ⇒ Enumerator<Pathname> #find_dirs {|descendent| ... } ⇒ Pathname
Iterates over all (recursive) descendent directories of the directory indicated by the Pathname. Iterated Pathnames are prefixed by the original Pathname, and are in depth-first order.
If no block is given, this method returns an Enumerator. Otherwise, the block is called with each descendent Pathname, and this method returns the original Pathname.
157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/pleasant_path/pathname.rb', line 157 def find_dirs return to_enum(__method__) unless block_given? self.find do |path| if path.file? Find.prune elsif path != self yield path end end self end |
#find_files ⇒ Enumerator<Pathname> #find_files {|descendent| ... } ⇒ Pathname
Iterates over all (recursive) descendent files of the directory indicated by the Pathname. Iterated Pathnames are prefixed by the original Pathname, and are in depth-first order.
If no block is given, this method returns an Enumerator. Otherwise, the block is called with each descendent Pathname, and this method returns the original Pathname.
233 234 235 236 237 238 239 240 241 |
# File 'lib/pleasant_path/pathname.rb', line 233 def find_files return to_enum(__method__) unless block_given? self.find do |path| yield path if path.file? end self end |
#load_json(options = {}) ⇒ Object
Parses the contents of the file indicated by the Pathname as JSON, deserializing arbitrary data types via type information embedded in the JSON. This is UNSAFE for JSON from an untrusted source. To consume untrusted JSON, use #read_json instead.
For information about options, see JSON.parse. By default, this method uses JSON.load_default_options.
For information about serializing custom types to JSON, see the JSON readme.
51 52 53 |
# File 'lib/pleasant_path/json/pathname.rb', line 51 def load_json( = {}) JSON.load(self, nil, ) end |
#load_yaml ⇒ Object
Parses the contents of the file indicated by the Pathname as YAML, deserializing arbitrary data types via type information embedded in the YAML. This is UNSAFE for YAML from an untrusted source. To consume untrusted YAML, use #read_yaml instead.
39 40 41 |
# File 'lib/pleasant_path/yaml/pathname.rb', line 39 def load_yaml YAML.load_file(self) end |
#make_dir ⇒ self
Creates the directory indicated by the Pathname, including any necessary parent directories. Returns the Pathname.
299 300 301 302 |
# File 'lib/pleasant_path/pathname.rb', line 299 def make_dir self.mkpath self end |
#make_dirname ⇒ self
Creates the directory indicated by the Pathname dirname, including any necessary parent directories. Returns the Pathname.
321 322 323 324 |
# File 'lib/pleasant_path/pathname.rb', line 321 def make_dirname self.dirname.make_dir self end |
#make_file ⇒ Pathname
Creates the file indicated by the Pathname, including any necessary parent directories. Returns the Pathname.
342 343 344 345 |
# File 'lib/pleasant_path/pathname.rb', line 342 def make_file self.make_dirname.open("a"){} self end |
#move(destination) ⇒ Pathname
Moves the file or directory indicated by the Pathname to destination, in the same manner as FileUtils.mv. Creates any necessary parent directories of the destination. Returns destination as a Pathname.
475 476 477 478 479 480 |
# File 'lib/pleasant_path/pathname.rb', line 475 def move(destination) destination = destination.to_pathname destination.make_dirname FileUtils.mv(self, destination) destination end |
#move_as(destination) ⇒ Pathname #move_as(destination) {|source, destination| ... } ⇒ Pathname Also known as: rename_as
Moves the file or directory indicated by the Pathname to a destination, replacing any existing file or directory.
If a block is given and a file or directory does exist at the destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the move is aborted.
Creates any necessary parent directories of the destination. Returns the destination as a Pathname (or the source Pathname in the case that the move is aborted).
WARNING: Due to system API limitations, the move is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is moved to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
# File 'lib/pleasant_path/pathname.rb', line 560 def move_as(destination) destination = destination.to_pathname if block_given? && destination.exist? && self.exist? && !File.identical?(self, destination) destination = (yield self, destination) || self end if destination != self if File.identical?(self, destination) # FileUtils.mv raises an ArgumentError when both paths refer to # the same file. On case-insensitive file systems, this occurs # even when both paths have different casing. We want to # disregard the ArgumentError at all times, and change the # filename casing when applicable. File.rename(self, destination) else destination.delete! self.move(destination) end end destination end |
#move_into(directory) ⇒ Pathname #move_into(directory) {|source, destination| ... } ⇒ Pathname
Moves the file or directory indicated by the Pathname into directory, replacing any existing file or directory of the same basename.
If a block is given and a file or directory does exist at the resultant destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the move is aborted.
Creates any necessary parent directories of the destination. Returns the destination as a Pathname (or the source Pathname in the case that the move is aborted).
WARNING: Due to system API limitations, the move is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is moved to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.
641 642 643 |
# File 'lib/pleasant_path/pathname.rb', line 641 def move_into(directory, &block) self.move_as(directory / self.basename, &block) end |
#parentname ⇒ Pathname
Returns the basename of the parent directory (dirname).
39 40 41 |
# File 'lib/pleasant_path/pathname.rb', line 39 def parentname self.dirname.basename end |
#read_json(options = {}) ⇒ nil, ...
Parses the contents of the file indicated by the Pathname as JSON. The returned result will composed of only basic data types, e.g. nil, true, false, Numeric, String, Array, and Hash.
For information about options, see JSON.parse. By default, this method uses JSON.load_default_options plus create_additions: false.
22 23 24 |
# File 'lib/pleasant_path/json/pathname.rb', line 22 def read_json( = {}) JSON.load(self, nil, { create_additions: false, ** }) end |
#read_lines(eol: $/) ⇒ Array<String>
Not to be confused with Pathname#readlines, which retains end-of-line (EOL) characters.
Reads all lines from the file indicated by the Pathname, and returns them with all end-of-line (EOL) characters stripped.
1081 1082 1083 |
# File 'lib/pleasant_path/pathname.rb', line 1081 def read_lines(eol: $/) self.open("r"){|f| f.read_lines(eol: eol) } end |
#read_yaml ⇒ nil, ...
Parses the contents of the file indicated by the Pathname as YAML. The returned result will composed of only basic data types, e.g. nil, true, false, Numeric, String, Array, and Hash.
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/pleasant_path/yaml/pathname.rb', line 15 def read_yaml self.open("r") do |f| # HACK fix Ruby 2.6 warning, but still support Ruby < 2.6 if Gem::Version.new(Psych::VERSION) >= Gem::Version.new("3.1.0.pre1") YAML.safe_load(f, filename: self) else YAML.safe_load(f, [], [], false, self) end end end |
#rename_basename(new_basename) ⇒ Pathname #rename_basename(new_basename) {|source, destination| ... } ⇒ Pathname
Renames the file or directory indicated by the Pathname relative to its dirname, replacing any existing file or directory of the same basename.
If a block is given and a file or directory does exist at the resultant destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the rename is aborted.
Returns the destination as a Pathname (or the source Pathname in the case that the rename is aborted).
WARNING: Due to system API limitations, the rename is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is moved to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.
891 892 893 |
# File 'lib/pleasant_path/pathname.rb', line 891 def rename_basename(new_basename, &block) self.move_as(self.dirname / new_basename, &block) end |
#rename_extname(new_extname) ⇒ Pathname #rename_extname(new_extname) {|source, destination| ... } ⇒ Pathname
Changes the file extension (extname) of the file indicated by the Pathname, replacing any existing file or directory of the same resultant basename.
If a block is given and a file or directory does exist at the resultant destination, the block is called with the source and destination Pathnames, and the return value of the block is used as the new destination. If the block returns the source Pathname or nil, the rename is aborted.
Returns the destination as a Pathname (or the source Pathname in the case that the rename is aborted).
WARNING: Due to system API limitations, the rename is performed in two steps, non-atomically. First, any file or directory existing at the destination is deleted. Next, the source is moved to the destination. The second step can fail independently of the first, e.g. due to insufficient disk space, leaving the file or directory previously at the destination deleted without replacement.
970 971 972 973 974 975 |
# File 'lib/pleasant_path/pathname.rb', line 970 def rename_extname(new_extname, &block) unless new_extname.start_with?(".") || new_extname.empty? new_extname = ".#{new_extname}" end self.move_as(self.sub_ext(new_extname), &block) end |
#to_pathname ⇒ self
Returns the Pathname unmodified. Exists for parity with String#to_pathname.
14 15 16 |
# File 'lib/pleasant_path/pathname.rb', line 14 def to_pathname self end |
#touch_file ⇒ self
Use #make_file.
Creates the file indicated by the Pathname, including any necessary parent directories. If the file already exists, its modification time (mtime) and access time (atime) are updated. Returns the Pathname.
367 368 369 370 371 |
# File 'lib/pleasant_path/pathname.rb', line 367 def touch_file self.make_dirname FileUtils.touch(self) self end |
#write_lines(lines, eol: $/) ⇒ self
Writes each object in lines as a string plus end-of-line (EOL) characters to the file indicated by the Pathname, overwriting the file if it exists. Creates the file if it does not exist, including any necessary parent directories. Returns the Pathname.
1035 1036 1037 1038 |
# File 'lib/pleasant_path/pathname.rb', line 1035 def write_lines(lines, eol: $/) self.make_dirname.open("w"){|f| f.write_lines(lines, eol: eol) } self end |
#write_text(text) ⇒ self
Writes text to the file indicated by the Pathname, overwriting the file if it exists. Creates the file if it does not exist, including any necessary parent directories. Returns the Pathname.
993 994 995 996 |
# File 'lib/pleasant_path/pathname.rb', line 993 def write_text(text) self.make_dirname.open("w"){|f| f.write(text) } self end |