Class: Pathname

Inherits:
Object show all
Defined in:
lib/pleasant_path/pathname.rb,
lib/pleasant_path/json/pathname.rb,
lib/pleasant_path/yaml/pathname.rb

Constant Summary collapse

NULL =

File::NULL as a Pathname. On POSIX systems, this should be equivalent to Pathname.new(“/dev/null”).

Pathname.new(File::NULL)

Instance Method Summary collapse

Instance Method Details

#^(sibling) ⇒ Pathname

Joins the parent (dirname) of the Pathname with the argument. The mnemonic for this operator is that the resultant path goes up one directory level from the original, then goes down to the directory specified by the argument.

Examples:

Pathname.new("path/to/file1") ^ "file2"  # == Pathname.new("path/to/file2")

Parameters:

Returns:



26
27
28
# File 'lib/pleasant_path/pathname.rb', line 26

def ^(sibling)
  self.dirname / sibling
end

#append_file(source) ⇒ Pathname

Appends the contents of another file to the destination indicated by Pathname. Returns the destination Pathname.

Examples:

File.read("yearly.log")  # == "one\ntwo\n"
File.read("daily.log")   # == "three\nfour\n"

Pathname.new("yearly.log").append_file("daily.log")
  # == Pathname.new("yearly.log")

File.read("yearly.log")  # == "one\ntwo\nthree\nfour\n"

Parameters:

Returns:



627
628
629
630
# File 'lib/pleasant_path/pathname.rb', line 627

def append_file(source)
  self.open("a"){|destination| IO::copy_stream(source, destination) }
  self
end

#append_lines(lines) ⇒ Pathname

Appends each object as a string plus a succeeding new line character ($/) to the file indicated by the Pathname. Returns the Pathname. The file is created if it does not exist. Any necessary parent directories are created if they do not exist.

Examples:

File.exist?("path/to/file")  # false

Pathname.new("path/to/file").append_lines([:one, :two]).append_lines([:three, :four])
  # == Pathname.new("path/to/file")

File.read("path/to/file")    # == "one\ntwo\nthree\nfour\n"

Parameters:

  • lines (Enumerable<#to_s>)

Returns:



536
537
538
539
# File 'lib/pleasant_path/pathname.rb', line 536

def append_lines(lines)
  self.make_dirname.open("a"){|f| f.write_lines(lines) }
  self
end

#append_text(text) ⇒ Pathname

Appends given text to the file indicated by the Pathname, and returns the Pathname. The file is created if it does not exist. Any necessary parent directories are created if they do not exist.

Examples:

Dir.exist?("path")           # == false
Dir.exist?("path/to")        # == false
File.exist?("path/to/file")  # == false

Pathname.new("path/to/file").append_text("hello").append_text(" world")
  # == Pathname.new("path/to/file")

File.read("path/to/file")    # == "hello world"

Parameters:

Returns:



496
497
498
499
# File 'lib/pleasant_path/pathname.rb', line 496

def append_text(text)
  self.make_dirname.open("a"){|f| f.write(text) }
  self
end

#chdirPathname #chdir {|path| ... } ⇒ block_retval

Changes the current working directory to the directory indicated by the Pathname. If a block is given, it is called with the Pathname, and the original working directory is restored after the block exits.

Returns the return value of the block, if one is given. Otherwise, returns the Pathname.

Raises an exception if the directory indicated by the Pathname does not exist.

See also Dir::chdir.

Examples:

FileUtils.mkdir("dir1")
FileUtils.mkdir("dir2")

Pathname.new("dir1").chdir  # == Pathname.new("dir1")
Pathname.pwd                # == Pathname.new("dir1")

Pathname.new("dir2").chdir{|path| "in #{path}" }  # == "in dir2"
Pathname.pwd                                      # == Pathname.new("dir1")

Overloads:

  • #chdirPathname

    Returns:

  • #chdir {|path| ... } ⇒ block_retval

    Yield Parameters:

    Yield Returns:

    Returns:

    • (block_retval)

Raises:

  • (SystemCallError)

    if the directory does not exist



214
215
216
217
218
219
220
221
222
223
# File 'lib/pleasant_path/pathname.rb', line 214

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

Computes the longest path that the Pathname and other have in common. See also File.common_path.

Examples:

f1 = Pathname.new("dir1/file1")
f2 = Pathname.new("dir1/subdir1/file2")
f3 = Pathname.new("dir1/subdir1/file3")
f4 = Pathname.new("dir2/file4")

f1.common_path(f2)  # == Pathname.new("dir1/")
f2.common_path(f3)  # == Pathname.new("dir1/subdir1/")
f3.common_path(f4)  # == Pathname.new("")

[f1, f2, f3].reduce(&:common_path)  # == Pathname.new("dir1/")

Parameters:

Returns:



73
74
75
# File 'lib/pleasant_path/pathname.rb', line 73

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 the given destination, and returns that destination as a Pathname. Creates any necessary parent directories if they do not exist. See also FileUtils.cp_r.

Examples:

File.exist?("path/to/file")      # == true
Dir.exist?("some")               # == false
Dir.exist?("some/other")         # == false
File.exist?("some/other/thing")  # == false

Pathname.new("path/to/file").copy("some/other/thing")
  # == Pathname.new("some/other/thing")

File.exist?("path/to/file")      # == true
Dir.exist?("some")               # == true
Dir.exist?("some/other")         # == true
File.exist?("some/other/thing")  # == true

Parameters:

Returns:



375
376
377
378
379
380
# File 'lib/pleasant_path/pathname.rb', line 375

def copy(destination)
  destination = destination.to_pathname
  destination.make_dirname
  FileUtils.cp_r(self, destination)
  destination
end

#copy_into(directory) ⇒ Pathname

Copies the file or directory indicated by the Pathname into the given directory, and returns the resultant path as a Pathname. Creates any necessary parent directories if they do not exist.

Examples:

File.exist?("path/to/file")     # == true
Dir.exist?("other")             # == false
Dir.exist?("other/path")        # == false
File.exist?("other/path/file")  # == false

Pathname.new("path/to/file").copy_into("other/path")
  # == Pathname.new("other/path/file")

File.exist?("path/to/file")     # == true
Dir.exist?("other")             # == true
Dir.exist?("other/path")        # == true
File.exist?("other/path/file")  # == true

Parameters:

Returns:



402
403
404
# File 'lib/pleasant_path/pathname.rb', line 402

def copy_into(directory)
  self.copy(directory / self.basename)
end

#delete!Pathname

Recursively deletes the directory or file indicated by the Pathname, and returns the Pathname. Similar to Pathname#rmtree, but does not raise an exception if the file does not exist.

Examples:

File.exist?("path/to/file")   # == true

Pathname.new("path").delete!  # == Pathname.new("path")

Dir.exist?("path")            # == false
Dir.exist?("path/to")         # == false
File.exist?("path/to/file")   # == false

Returns:



297
298
299
300
# File 'lib/pleasant_path/pathname.rb', line 297

def delete!
  self.rmtree if self.exist?
  self
end

#dir_empty?Boolean

True if the directory indicated by the Pathname contains no other directories or files.

Examples:

FileUtils.mkdir("parent")
FileUtils.mkdir("parent/dir1")

Pathname.new("parent").dir_empty?       # == false
Pathname.new("parent/dir1").dir_empty?  # == true

Returns:

  • (Boolean)


93
94
95
# File 'lib/pleasant_path/pathname.rb', line 93

def dir_empty?
  self.children(false).empty?
end

#dirsArray<Pathname>

Returns the immediate (non-recursive) child directories of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname.

Examples:

FileUtils.mkdir("parent")
FileUtils.mkdir("parent/dir1")
FileUtils.mkdir("parent/dir2")
FileUtils.touch("parent/file1")

Pathname.new("parent").dirs
  # == [
  #      Pathname.new("parent/dir1"),
  #      Pathname.new("parent/dir2")
  #    ]

Returns:



114
115
116
# File 'lib/pleasant_path/pathname.rb', line 114

def dirs
  self.children.tap{|c| c.select!(&:dir?) }
end

#dirs_rArray<Pathname>

Returns the recursively descended child directories of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname.

Examples:

FileUtils.mkdir("parent")
FileUtils.mkdir("parent/dir1")
FileUtils.mkdir("parent/dir1/dir1")
FileUtils.mkdir("parent/dir2")
FileUtils.touch("parent/dir2/file1")

Pathname.new("parent").dirs_r
  # == [
  #      Pathname.new("parent/dir1"),
  #      Pathname.new("parent/dir1/dir1"),
  #      Pathname.new("parent/dir2")
  #    ]

Returns:



137
138
139
# File 'lib/pleasant_path/pathname.rb', line 137

def dirs_r
  self.find.select(&:dir?).tap(&:shift)
end

#edit_lines {|lines| ... } ⇒ Array<String>

Reads the contents of the file indicated by the Pathname into memory as an array of lines, and yields the array to the given block for editing. Writes the return value of the block back to the file, overwriting previous contents. The $/ global string specifies what end-of-line characters to use for both reading and writing. Returns the array of lines that comprises the file’s new contents. See also File.edit_lines.

Examples:

dedup lines of file

File.read("entries.txt")  # == "AAA\nBBB\nBBB\nCCC\nAAA\n"

Pathname.new("entries.txt").edit_lines(&:uniq)
  # == ["AAA", "BBB", "CCC"]

File.read("entries.txt")  # == "AAA\nBBB\nCCC\n"

Yields:

  • (lines)

    edits current file contents

Yield Parameters:

Yield Returns:

Returns:



609
610
611
# File 'lib/pleasant_path/pathname.rb', line 609

def edit_lines(&block)
  File.edit_lines(self, &block)
end

#edit_text {|text| ... } ⇒ String

Reads the contents of the file indicated by the Pathname into memory as a string, and yields the string to the given block for editing. Writes the return value of the block back to the file, overwriting previous contents. Returns the file’s new contents. See also File.edit_text.

Examples:

update JSON data file

File.read("data.json")  # == '{"nested":{"key":"value"}}'

Pathname.new("data.json").edit_text do |text|
  data = JSON.parse(text)
  data["nested"]["key"] = "new value"
  data.to_json
end                     # == '{"nested":{"key":"new value"}}'

File.read("data.json")  # == '{"nested":{"key":"new value"}}'

Yields:

  • (text)

    edits current file contents

Yield Parameters:

  • text (String)

    current contents

Yield Returns:

Returns:



585
586
587
# File 'lib/pleasant_path/pathname.rb', line 585

def edit_text(&block)
  File.edit_text(self, &block)
end

#existencePathname?

Returns the Pathname if exist? returns true, otherwise returns nil.

Examples:

FileUtils.mkdir("dir1")
FileUtils.touch("dir1/file1")

Pathname.new("dir1/file1").existence  # == Pathname.new("dir1/file1")

Pathname.new("dir1/file2").existence  # == nil

Returns:



52
53
54
# File 'lib/pleasant_path/pathname.rb', line 52

def existence
  self if self.exist?
end

#filesArray<Pathname>

Returns the immediate (non-recursive) child files of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname.

Examples:

FileUtils.mkdir("parent")
FileUtils.touch("parent/file1")
FileUtils.touch("parent/file2")
FileUtils.mkdir("parent/dir1")

Pathname.new("parent").files
  # == [
  #      Pathname.new("parent/file1"),
  #      Pathname.new("parent/file2")
  #    ]

Returns:



158
159
160
# File 'lib/pleasant_path/pathname.rb', line 158

def files
  self.children.tap{|c| c.select!(&:file?) }
end

#files_rArray<Pathname>

Returns the recursively descended child files of the directory indicated by the Pathname. Returned Pathnames are prefixed by the original Pathname.

Examples:

FileUtils.mkdir("parent")
FileUtils.mkdir("parent/dir1")
FileUtils.touch("parent/dir1/file1")
FileUtils.touch("parent/file1")

Pathname.new("parent").files_r
  # == [
  #      Pathname.new("parent/dir1/file1"),
  #      Pathname.new("parent/file1")
  #    ]

Returns:



179
180
181
# File 'lib/pleasant_path/pathname.rb', line 179

def files_r
  self.find.select(&:file?)
end

#load_json(options = {}) ⇒ Object

Reads the contents of the file indicated by the Pathname, and parses it as JSON. The parser will use type information embedded in the JSON to deserialize custom types. This is UNSAFE for JSON from an untrusted source. To consume untrusted JSON, use #read_json instead.

For information about available options, see JSON.parse.

For information about serializing custom types to JSON, see the JSON readme.

Examples:

require "json/add/core" # provides Struct#to_json
Point = Struct.new(:x, :y)
point = Point.new(10, 20)
File.write("in.json", point.to_json)

Pathname.new("in.json").load_json  # == Point.new(10, 20)

Parameters:

  • options (Hash) (defaults to: {})

Returns:

  • deserialized object



54
55
56
# File 'lib/pleasant_path/json/pathname.rb', line 54

def load_json(options = {})
  self.open("r"){|f| JSON.load(f, nil, options) }
end

#load_yamlObject

Reads the contents of the file indicated by the Pathname, and parses it as YAML. The parser will use type information embedded in the YAML to deserialize custom types. This is UNSAFE for YAML from an untrusted source. To consume untrusted YAML, use #read_yaml instead.

Examples:

Point = Struct.new(:x, :y)
point = Point.new(10, 20)
File.write("in.yaml", point.to_yaml)

Pathname.new("in.yaml").load_yaml  # == Point.new(10, 20)

Returns:

  • deserialized object



32
33
34
# File 'lib/pleasant_path/yaml/pathname.rb', line 32

def load_yaml
  YAML.load_file(self)
end

#make_dirPathname

Alias of Pathname#mkpath, but this method returns the Pathname.

Examples:

Dir.exist?("path")                # == false
Dir.exist?("path/to")             # == false

Pathname.new("path/to").make_dir  # == Pathname.new("path/to")

Dir.exist?("path")                # == true
Dir.exist?("path/to")             # == true

Returns:



237
238
239
240
# File 'lib/pleasant_path/pathname.rb', line 237

def make_dir
  self.mkpath
  self
end

#make_dirnamePathname

Creates the parent (dirname) directories of the Pathname if they do not exist, and returns the Pathname.

Examples:

Dir.exist?("path")                         # == false
Dir.exist?("path/to")                      # == false

Pathname.new("path/to/file").make_dirname  # == Pathname.new("path/to/file")

Dir.exist?("path")                         # == true
Dir.exist?("path/to")                      # == true
Dir.exist?("path/to/file")                 # == false

Returns:



256
257
258
259
# File 'lib/pleasant_path/pathname.rb', line 256

def make_dirname
  self.dirname.make_dir
  self
end

#move(destination) ⇒ Pathname

Moves the file or directory indicated by the Pathname to the given destination, and returns that destination as a Pathname. Creates any necessary parent directories if they do not exist. See also FileUtils.mv.

Examples:

File.exist?("path/to/file")      # == true
Dir.exist?("some")               # == false
Dir.exist?("some/other")         # == false
File.exist?("some/other/thing")  # == false

Pathname.new("path/to/file").move("some/other/thing")
  # == Pathname.new("some/other/thing")

File.exist?("path/to/file")      # == false
Dir.exist?("some")               # == true
Dir.exist?("some/other")         # == true
File.exist?("some/other/thing")  # == true

Parameters:

Returns:



323
324
325
326
327
328
# File 'lib/pleasant_path/pathname.rb', line 323

def move(destination)
  destination = destination.to_pathname
  destination.make_dirname
  FileUtils.mv(self, destination)
  destination
end

#move_into(directory) ⇒ Pathname

Moves the file or directory indicated by the Pathname into the given directory, and returns the resultant path as a Pathname. Creates any necessary parent directories if they do not exist.

Examples:

File.exist?("path/to/file")     # == true
Dir.exist?("other")             # == false
Dir.exist?("other/path")        # == false
File.exist?("other/path/file")  # == false

Pathname.new("path/to/file").move_into("other/path")
  # == Pathname.new("other/path/file")

File.exist?("path/to/file")     # == false
Dir.exist?("other")             # == true
Dir.exist?("other/path")        # == true
File.exist?("other/path/file")  # == true

Parameters:

Returns:



350
351
352
# File 'lib/pleasant_path/pathname.rb', line 350

def move_into(directory)
  self.move(directory / self.basename)
end

#parentnamePathname

Returns the basename of the Pathname’s parent directory.

Examples:

Pathname.new("path/to/file").parentname  # == Pathname.new("to")

Returns:



36
37
38
# File 'lib/pleasant_path/pathname.rb', line 36

def parentname
  self.dirname.basename
end

#read_json(options = {}) ⇒ nil, ...

Reads the contents of the file indicated by the Pathname, and parses it as JSON. The returned result will be a basic Ruby data structure, namely, one of: nil, true, false, a Numeric, a String, an Array, or a Hash.

For information about available options, see JSON.parse.

Examples:

File.write("in.json", '{"key": "value"}')

Pathname.new("in.json").read_json  # == { "key" => "value" }

Parameters:

  • options (Hash) (defaults to: {})

Returns:

  • (nil, true, false, Numeric, String, Symbol, Array, Hash)


19
20
21
22
23
24
25
26
27
28
# File 'lib/pleasant_path/json/pathname.rb', line 19

def read_json(options = {})
  options = {
    quirks_mode: true,
    allow_nan: true,
    max_nesting: false,
    create_additions: false,
  }.merge(options)

  JSON.parse(self.read_text, options)
end

#read_linesArray<String>

Reads from the file indicated by the Pathname all lines, and returns them as an array, end-of-line characters excluded. The $/ global string specifies what end-of-line characters to look for. See also IO#read_lines.

(Not to be confused with Pathname#readlines which retains end-of-line characters in every string it returns.)

Examples:

File.read("path/to/file")                # == "one\ntwo\n"

Pathname.new("path/to/file").read_lines  # == ["one", "two"]

Returns:



560
561
562
# File 'lib/pleasant_path/pathname.rb', line 560

def read_lines
  self.open("r"){|f| f.read_lines }
end

#read_yamlnil, ...

Reads the contents of the file indicated by the Pathname, and parses it as YAML. The returned result will be a basic Ruby data structure, namely, one of: nil, true, false, a Numeric, a String, an Array, or a Hash.

Examples:

File.write("in.yaml", "key: value")

Pathname.new("in.yaml").read_yaml  # == { "key" => "value" }

Returns:



14
15
16
# File 'lib/pleasant_path/yaml/pathname.rb', line 14

def read_yaml
  self.open("r"){|f| YAML.safe_load(f, [], [], false, self) }
end

#rename_basename(new_basename) ⇒ Pathname

Renames the file or directory indicated by the Pathname, but preserves its location as indicated by dirname. Returns the resultant path as a Pathname.

Examples:

File.exist?("path/to/file")   # == true

Pathname.new("path/to/file").rename_basename("other")
  # == Pathname.new("path/to/other")

File.exist?("path/to/file")   # == false
File.exist?("path/to/other")  # == true

Parameters:

Returns:



421
422
423
424
425
# File 'lib/pleasant_path/pathname.rb', line 421

def rename_basename(new_basename)
  new_path = self.dirname / new_basename
  self.rename(new_path)
  new_path
end

#rename_extname(new_extname) ⇒ Pathname

Renames the file extension of the file indicated by the Pathname. If the file has no extension, the new extension is appended.

Examples:

replace extension

File.exist?("path/to/file.abc")   # == true

Pathname.new("path/to/file.abc").rename_extname(".xyz")
  # == Pathname.new("path/to/file.xyz")

File.exist?("path/to/file.abc")   # == false
File.exist?("path/to/file.xyz")   # == true

remove extension

File.exist?("path/to/file.abc")   # == true

Pathname.new("path/to/file.abc").rename_extname("")
  # == Pathname.new("path/to/file")

File.exist?("path/to/file.abc")   # == false
File.exist?("path/to/file")       # == true

Parameters:

Returns:



450
451
452
453
454
455
456
457
# File 'lib/pleasant_path/pathname.rb', line 450

def rename_extname(new_extname)
  unless new_extname.start_with?(".") || new_extname.empty?
    new_extname = ".#{new_extname}"
  end
  new_path = self.sub_ext(new_extname)
  self.rename(new_path)
  new_path
end

#to_pathnamePathname

Returns the Pathname unmodified. Exists for parity with String#to_pathname.

Returns:



12
13
14
# File 'lib/pleasant_path/pathname.rb', line 12

def to_pathname
  self
end

#touch_filePathname

Updates the modification time (mtime) and access time (atime) of the file indicated by the Pathname, and returns the Pathname. Creates the file and any necessary parent directories if they do not exist. See also FileUtils.touch.

Examples:

Dir.exist?("path")                       # == false
Dir.exist?("path/to")                    # == false

Pathname.new("path/to/file").touch_file  # == Pathname.new("path/to/file")

Dir.exist?("path")                       # == true
Dir.exist?("path/to")                    # == true
File.exist?("path/to/file")              # == true

Returns:



277
278
279
280
281
# File 'lib/pleasant_path/pathname.rb', line 277

def touch_file
  self.make_dirname
  FileUtils.touch(self)
  self
end

#write_lines(lines) ⇒ Pathname

Writes each object as a string plus a succeeding new line character ($/) to the file indicated by the Pathname. Returns the Pathname. The file is overwritten if it already exists. Any necessary parent directories are created if they do not exist.

Examples:

File.exist?("path/to/file")  # false

Pathname.new("path/to/file").write_lines([:one, :two])
  # == Pathname.new("path/to/file")

File.read("path/to/file")    # == "one\ntwo\n"

Parameters:

  • lines (Enumerable<#to_s>)

Returns:



516
517
518
519
# File 'lib/pleasant_path/pathname.rb', line 516

def write_lines(lines)
  self.make_dirname.open("w"){|f| f.write_lines(lines) }
  self
end

#write_text(text) ⇒ Pathname

Writes given text to the file indicated by the Pathname, and returns the Pathname. The file is overwritten if it already exists. Any necessary parent directories are created if they do not exist.

Examples:

Dir.exist?("path")           # == false
Dir.exist?("path/to")        # == false
File.exist?("path/to/file")  # == false

Pathname.new("path/to/file").write_text("hello world")
  # == Pathname.new("path/to/file")

File.read("path/to/file")    # == "hello world"

Parameters:

Returns:



475
476
477
478
# File 'lib/pleasant_path/pathname.rb', line 475

def write_text(text)
  self.make_dirname.open("w"){|f| f.write(text) }
  self
end