Class: Pathname

Inherits:
String show all
Defined in:
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb,
lib/pathname3.rb

Overview

Pathname represents a path to a file on a filesystem. It can be relative or absolute. It exists to provide a more instance-oriented approach to managing paths than the class-level methods on File, FileTest, Dir, and Find.

Constant Summary collapse

SYMLOOP_MAX =

deepest symlink traversal

8
ROOT =
'/'.freeze
DOT =
'.'.freeze
DOT_DOT =
'..'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Pathname

Creates a new Pathname. Any path with a null is rejected.



19
20
21
22
23
24
25
# File 'lib/pathname3.rb', line 19

def initialize(path)
  if path =~ %r{\0}
    raise ArgumentError, "path cannot contain ASCII NULLs"
  end

  super(path)
end

Class Method Details

.[](pattern) ⇒ Object

See Dir::[]



317
# File 'lib/pathname3.rb', line 317

def self.[](pattern); Dir[pattern].map! {|d| d.to_path }; end

.glob(pattern, flags = 0) ⇒ Object

See Dir::glob



335
336
337
338
339
340
341
342
343
344
345
# File 'lib/pathname3.rb', line 335

def self.glob(pattern, flags = 0)
  dirs = Dir.glob(pattern, flags)
  dirs.map! {|path| path.to_path }

  if block_given?
    dirs.each {|dir| yield dir }
    nil
  else
    dirs
  end
end

.join(*parts) ⇒ Object

See File::join



454
# File 'lib/pathname3.rb', line 454

def self.join(*parts); File.join(*parts.reject {|p| p.empty? }).to_path; end

.pwdObject Also known as: getwd

See Dir::pwd



320
# File 'lib/pathname3.rb', line 320

def self.pwd; Dir.pwd.to_path; end

Instance Method Details

#+(path) ⇒ Object

Appends a component of a path to self. Returns a Pathname to the combined path. Cleans any redundant components of the path.



54
55
56
# File 'lib/pathname3.rb', line 54

def +(path)
  dup << path
end

#<<(path) ⇒ Object

Appends (destructively) a component of a path to self. Replaces the contents of the current Pathname with the new, combined path. Cleans any redundant components of the path.



63
64
65
# File 'lib/pathname3.rb', line 63

def <<(path)
  replace( join(path).cleanpath! )
end

#<=>(other) ⇒ Object

Compares pathnames, case-sensitively. Sorts directories higher than other files named similarly.



31
32
33
34
35
# File 'lib/pathname3.rb', line 31

def <=>(other)
  self.tr('/', "\0").to_s <=> other.to_str.tr('/', "\0")
rescue NoMethodError # doesn't respond to to_str
  nil
end

#==(other) ⇒ Object

Compares two pathnames for equality. Considers pathnames equal if they both point to the same location, and are both absolute or both relative.



41
42
43
44
45
46
47
48
# File 'lib/pathname3.rb', line 41

def ==(other)
  left  =                 self.cleanpath.tr('/', "\0").to_s
  right = other.to_str.to_path.cleanpath.tr('/', "\0").to_s

  left == right
rescue NoMethodError # doesn't implement to_str
  false
end

#absolute?Boolean

Returns true if this is an absolute path.

Returns:

  • (Boolean)


70
71
72
# File 'lib/pathname3.rb', line 70

def absolute?
  self[0, 1].to_s == ROOT
end

#ascendObject

Yields to each component of the path, going up to the root.

 Pathname.new('/path/to/some/file').ascend {|path| p path }
   "/path/to/some/file"
   "/path/to/some"
   "/path/to"
   "/path"
   "/"

 Pathname.new('a/relative/path').ascend {|path| p path }
   "a/relative/path"
   "a/relative"
   "a"

Does not actually access the filesystem.


91
92
93
94
95
96
# File 'lib/pathname3.rb', line 91

def ascend
  parts = to_a
  parts.length.downto(1) do |i|
    yield self.class.join(parts[0, i])
  end
end

#atimeObject

See File::atime



431
# File 'lib/pathname3.rb', line 431

def atime; File.atime(self); end

#basenameObject

See File::basename



457
# File 'lib/pathname3.rb', line 457

def basename; File.basename(self).to_path; end

#blockdev?Boolean

See FileTest::blockdev?

Returns:

  • (Boolean)


363
# File 'lib/pathname3.rb', line 363

def blockdev?; FileTest.blockdev?(self); end

#chardev?Boolean

See FileTest::chardev?

Returns:

  • (Boolean)


366
# File 'lib/pathname3.rb', line 366

def chardev?; FileTest.chardev?(self); end

#chdirObject

See Dir::chdir



355
356
357
358
# File 'lib/pathname3.rb', line 355

def chdir
  blk = lambda { yield self } if block_given?
  Dir.chdir(self, &blk)
end

#childrenObject

Returns all children of this path. “.” and “..” are not included, since they aren’t under the current path.



102
103
104
# File 'lib/pathname3.rb', line 102

def children
  entries[2..-1]
end

#chmod(mode) ⇒ Object

See File::chmod



460
# File 'lib/pathname3.rb', line 460

def chmod(mode); File.chmod(mode, self); end

#chown(owner, group) ⇒ Object

See File::chown



463
# File 'lib/pathname3.rb', line 463

def chown(owner, group); File.chown(owner, group, self); end

#cleanpathObject

Cleans the path by removing consecutive slashes, and useless dots.



134
135
136
# File 'lib/pathname3.rb', line 134

def cleanpath
  dup.cleanpath!
end

#cleanpath!Object

Cleans the path by removing consecutive slashes, and useless dots. Replaces the contents of the current Pathname.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/pathname3.rb', line 110

def cleanpath!
  parts = to_a
  final = []

  parts.each do |part|
    case part
      when DOT     then next
      when DOT_DOT then
        case final.last
          when ROOT    then next
          when DOT_DOT then final.push(DOT_DOT)
          when nil     then final.push(DOT_DOT)
          else              final.pop
        end
      else final.push(part)
    end
  end

  replace(final.empty? ? DOT : self.class.join(*final))
end

#ctimeObject

See File::ctime



434
# File 'lib/pathname3.rb', line 434

def ctime; File.ctime(self); end

#descendObject

Yields to each component of the path, going down from the root.

 Pathname.new('/path/to/some/file').descend {|path| p path }
   "/"
   "/path"
   "/path/to"
   "/path/to/some"
   "/path/to/some/file"

 Pathname.new('a/relative/path').descend {|path| p path }
   "a"
   "a/relative"
   "a/relative/path"

Does not actually access the filesystem.


155
156
157
158
159
160
# File 'lib/pathname3.rb', line 155

def descend
  parts = to_a
  1.upto(parts.length) do |i|
    yield self.class.join(parts[0, i])
  end
end

#directory?Boolean

See FileTest::directory?

Returns:

  • (Boolean)


369
# File 'lib/pathname3.rb', line 369

def directory?; FileTest.directory?(self); end

#dirnameObject

See File::dirname



466
# File 'lib/pathname3.rb', line 466

def dirname; File.dirname(self).to_path; end

#dot?Boolean

Returns true if this path is simply a ‘.’.

Returns:

  • (Boolean)


165
166
167
# File 'lib/pathname3.rb', line 165

def dot?
  self == DOT
end

#dot_dot?Boolean

Returns true if this path is simply a ‘..’.

Returns:

  • (Boolean)


172
173
174
# File 'lib/pathname3.rb', line 172

def dot_dot?
  self == DOT_DOT
end

#each_filename(&blk) ⇒ Object

Iterates over every component of the path.

Pathname.new('/path/to/some/file').each_filename {|path| p path }
  "/"
  "path"
  "to"
  "some"
  "file"

Pathname.new('a/relative/path').each_filename {|part| p part }
  "a"
  "relative"
  "path"


191
192
193
# File 'lib/pathname3.rb', line 191

def each_filename(&blk)
  to_a.each(&blk)
end

#each_line(sep = $/, &blk) ⇒ Object

See IO::each_line



527
# File 'lib/pathname3.rb', line 527

def each_line(sep = $/, &blk); IO.foreach(self, sep, &blk); end

#entriesObject

See Dir::entries



323
# File 'lib/pathname3.rb', line 323

def entries; Dir.entries(self).map! {|e| e.to_path }; end

#executable?Boolean

See FileTest::executable?

Returns:

  • (Boolean)


372
# File 'lib/pathname3.rb', line 372

def executable?; FileTest.executable?(self); end

#executable_real?Boolean

See FileTest::executable_real?

Returns:

  • (Boolean)


375
# File 'lib/pathname3.rb', line 375

def executable_real?; FileTest.executable_real?(self); end

#exists?Boolean Also known as: exist?

See FileTest::exists?

Returns:

  • (Boolean)


378
# File 'lib/pathname3.rb', line 378

def exists?; FileTest.exists?(self); end

#expand_path(from = nil) ⇒ Object Also known as: absolute

See File::expand_path



469
# File 'lib/pathname3.rb', line 469

def expand_path(from = nil); File.expand_path(self, from).to_path; end

#extnameObject

See File::extname



472
# File 'lib/pathname3.rb', line 472

def extname; File.extname(self); end

#file?Boolean

See FileTest::file?

Returns:

  • (Boolean)


381
# File 'lib/pathname3.rb', line 381

def file?; FileTest.file?(self); end

#findObject

See Find::find



541
# File 'lib/pathname3.rb', line 541

def find; Find.find(self) {|path| yield path.to_path }; end

#fnmatch?(pat, flags = 0) ⇒ Boolean Also known as: fnmatch

See File::fnmatch

Returns:

  • (Boolean)


475
# File 'lib/pathname3.rb', line 475

def fnmatch?(pat, flags = 0); File.fnmatch(pat, self, flags); end

#ftypeObject

See File::ftype



437
# File 'lib/pathname3.rb', line 437

def ftype; File.ftype(self); end

#glob(pattern, flags = 0, &block) ⇒ Object

See Dir::glob



348
349
350
351
352
# File 'lib/pathname3.rb', line 348

def glob(pattern, flags = 0, &block)
  patterns = [pattern].flatten
  patterns.map! {|p| self.class.glob(self.to_s + p, flags, &block) }
  patterns.flatten
end

#grpowned?Boolean

See FileTest::grpowned?

Returns:

  • (Boolean)


384
# File 'lib/pathname3.rb', line 384

def grpowned?; FileTest.grpowned?(self); end

#join(*parts) ⇒ Object

See File::join



478
# File 'lib/pathname3.rb', line 478

def join(*parts); self.class.join(self, *parts); end

#lchmod(mode) ⇒ Object

See File::lchmod



481
# File 'lib/pathname3.rb', line 481

def lchmod(mode); File.lchmod(mode, self); end

#lchown(owner, group) ⇒ Object

See File::lchown



484
# File 'lib/pathname3.rb', line 484

def lchown(owner, group); File.lchown(owner, group, self); end

See File::link



487
# File 'lib/pathname3.rb', line 487

def link(to); File.link(self, to); end

#lstatObject

See File::lstat



440
# File 'lib/pathname3.rb', line 440

def lstat; File.lstat(self); end

#mkdir(mode = 0777) ⇒ Object

See Dir::mkdir



326
# File 'lib/pathname3.rb', line 326

def mkdir(mode = 0777); Dir.mkdir(self, mode); end

#mkpathObject

See FileUtils::mkpath



516
# File 'lib/pathname3.rb', line 516

def mkpath; FileUtils.mkpath(self).first.to_path; end

#mountpoint?Boolean

Returns true if the path is a mountpoint.

Returns:

  • (Boolean)


198
199
200
201
202
203
204
205
# File 'lib/pathname3.rb', line 198

def mountpoint?
  stat1 = self.lstat
  stat2 = self.parent.lstat

  stat1.dev != stat2.dev || stat1.ino == stat2.ino
rescue Errno::ENOENT
  false
end

#mtimeObject

See File::mtime



443
# File 'lib/pathname3.rb', line 443

def mtime; File.mtime(self); end

#open(mode = 'r', perm = nil, &blk) ⇒ Object

See File::open



490
# File 'lib/pathname3.rb', line 490

def open(mode = 'r', perm = nil, &blk); File.open(self, mode, perm, &blk); end

#opendir(&blk) ⇒ Object

See Dir::open



329
# File 'lib/pathname3.rb', line 329

def opendir(&blk); Dir.open(self, &blk); end

#owned?Boolean

See FileTest::owned?

Returns:

  • (Boolean)


387
# File 'lib/pathname3.rb', line 387

def owned?; FileTest.owned?(self); end

#parentObject

Returns a path to the parent directory. Simply appends a “..”.



210
211
212
# File 'lib/pathname3.rb', line 210

def parent
  self + '..'
end

#pipe?Boolean

See FileTest::pipe?

Returns:

  • (Boolean)


390
# File 'lib/pathname3.rb', line 390

def pipe?; FileTest.pipe?(self); end

#read(len = nil, off = 0) ⇒ Object

See IO::read



530
# File 'lib/pathname3.rb', line 530

def read(len = nil, off = 0); IO.read(self, len, off); end

#readable?Boolean

See FileTest::readable?

Returns:

  • (Boolean)


393
# File 'lib/pathname3.rb', line 393

def readable?; FileTest.readable?(self); end

#readable_real?Boolean

See FileTest::readable_real?

Returns:

  • (Boolean)


396
# File 'lib/pathname3.rb', line 396

def readable_real?; FileTest.readable_real?(self); end

#readlines(sep = $/) ⇒ Object

See IO::readlines



533
# File 'lib/pathname3.rb', line 533

def readlines(sep = $/); IO.readlines(self, sep); end

See File::readlink



493
# File 'lib/pathname3.rb', line 493

def readlink; File.readlink(self).to_path; end

#realpathObject

Resolves a path to locate a real location on the filesystem. Resolves symlinks up to a depth of SYMLOOP_MAX.



218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/pathname3.rb', line 218

def realpath
  path = self

  SYMLOOP_MAX.times do
    link = path.readlink
    link = path.dirname + link if link.relative?
    path = link
  end

  raise Errno::ELOOP, self
rescue Errno::EINVAL
  path.expand_path
end

#relative?Boolean

Returns true if this is a relative path.

Returns:

  • (Boolean)


235
236
237
# File 'lib/pathname3.rb', line 235

def relative?
  !absolute?
end

#relative_path_from(base) ⇒ Object

Returns this path as a relative location from base. The path and base must both be relative or both be absolute. An ArgumentError is raised if a relative path can’t be generated between the two locations.

Does not access the filesystem.



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/pathname3.rb', line 246

def relative_path_from(base)
  base = base.to_path

  # both must be relative, or both must be absolute
  if self.absolute? != base.absolute?
    raise ArgumentError, 'no relative path between a relative and absolute'
  end

  return self        if base.dot?
  return DOT.to_path if self == base

  base = base.cleanpath.to_a
  dest = self.cleanpath.to_a

  while !dest.empty? && !base.empty? && dest[0] == base[0]
    base.shift
    dest.shift
  end

  base.shift if base[0] == DOT
  dest.shift if dest[0] == DOT

  if base.include?(DOT_DOT)
    raise ArgumentError, "base directory may not contain '#{DOT_DOT}'"
  end

  path = base.fill(DOT_DOT) + dest
  path = self.class.join(*path)
  path = DOT.to_path if path.empty?

  path
end

#rename(to) ⇒ Object

See File::rename



496
# File 'lib/pathname3.rb', line 496

def rename(to); File.rename(self, to); replace(to); end

#rmdirObject

See Dir::rmdir



332
# File 'lib/pathname3.rb', line 332

def rmdir; Dir.rmdir(self); end

#rmtreeObject

See FileUtils::rmtree



519
# File 'lib/pathname3.rb', line 519

def rmtree; FileUtils.rmtree(self).first.to_path; end

#root?Boolean

Returns true if this path points to the root of the filesystem.

Returns:

  • (Boolean)


282
283
284
# File 'lib/pathname3.rb', line 282

def root?
  !!(self =~ %r{^#{ROOT}+$})
end

#setgid?Boolean

See FileTest::setgid?

Returns:

  • (Boolean)


399
# File 'lib/pathname3.rb', line 399

def setgid?; FileTest.setgit?(self); end

#setuid?Boolean

See FileTest::setuid?

Returns:

  • (Boolean)


402
# File 'lib/pathname3.rb', line 402

def setuid?; FileTest.setuid?(self); end

#sizeObject

See File::size



499
# File 'lib/pathname3.rb', line 499

def size; File.size(self); end

#size?Boolean

See File::size?

Returns:

  • (Boolean)


502
# File 'lib/pathname3.rb', line 502

def size?; File.size?(self); end

#socket?Boolean

See FileTest::socket?

Returns:

  • (Boolean)


405
# File 'lib/pathname3.rb', line 405

def socket?; FileTest.socket?(self); end

#splitObject

See File::split



505
# File 'lib/pathname3.rb', line 505

def split; File.split(self).map {|part| part.to_path }; end

#statObject

See File::stat



446
# File 'lib/pathname3.rb', line 446

def stat; File.stat(self); end

#sticky?Boolean

See FileTest::sticky?

Returns:

  • (Boolean)


408
# File 'lib/pathname3.rb', line 408

def sticky?; FileTest.sticky?(self); end

See File::symlink



508
# File 'lib/pathname3.rb', line 508

def symlink(to); File.symlink(self, to); end

#symlink?Boolean

See FileTest::symlink?

Returns:

  • (Boolean)


411
# File 'lib/pathname3.rb', line 411

def symlink?; FileTest.symlink?(self); end

#sysopen(mode = 'r', perm = nil) ⇒ Object

See IO::sysopen



536
# File 'lib/pathname3.rb', line 536

def sysopen(mode = 'r', perm = nil); IO.sysopen(self, mode, perm); end

#to_aObject

Splits the path into an array of its components.



289
290
291
292
293
294
# File 'lib/pathname3.rb', line 289

def to_a
  array = to_s.split(File::SEPARATOR)
  array.delete('')
  array.insert(0, ROOT) if absolute?
  array
end

#to_pathObject

Returns self.



299
300
301
# File 'lib/pathname3.rb', line 299

def to_path
  self
end

#touchObject

See FileUtils::touch



522
# File 'lib/pathname3.rb', line 522

def touch; FileUtils.touch(self).first.to_path; end

#truncateObject

See File::truncate



511
# File 'lib/pathname3.rb', line 511

def truncate; File.truncate(self); end

Unlinks the file or directory at the path.



306
307
308
309
310
311
312
# File 'lib/pathname3.rb', line 306

def unlink
  Dir.unlink(self)
  true
rescue Errno::ENOTDIR
  File.unlink(self)
  true
end

#utime(atime, mtime) ⇒ Object

See File::utime



449
# File 'lib/pathname3.rb', line 449

def utime(atime, mtime); File.utime(self, atime, mtime); end

#world_readable?Boolean

See FileTest::world_readable?

Returns:

  • (Boolean)


414
# File 'lib/pathname3.rb', line 414

def world_readable?; FileTest.world_readable?(self); end

#world_writable?Boolean

See FileTest::world_writable?

Returns:

  • (Boolean)


417
# File 'lib/pathname3.rb', line 417

def world_writable?; FileTest.world_writable?(self); end

#writable?Boolean

See FileTest::writable?

Returns:

  • (Boolean)


420
# File 'lib/pathname3.rb', line 420

def writable?; FileTest.writable?(self); end

#writable_real?Boolean

See FileTest::writable_real?

Returns:

  • (Boolean)


423
# File 'lib/pathname3.rb', line 423

def writable_real?; FileTest.writable_real?(self); end

#zero?Boolean

See FileTest::zero?

Returns:

  • (Boolean)


426
# File 'lib/pathname3.rb', line 426

def zero?; FileTest.zero?(self); end