Class Pathname
In: lib/pathname.rb
Parent: Object

Pathname

Pathname represents a pathname which locates a file in a filesystem. The pathname depends on OS: Unix, Windows, etc. Pathname library works with pathnames of local OS. However non-Unix pathnames are supported experimentally.

It does not represent the file itself. A Pathname can be relative or absolute. It‘s not until you try to reference the file that it even matters whether the file exists or not.

Pathname is immutable. It has no method for destructive update.

The value of this class is to manipulate file path information in a neater way than standard Ruby provides. The examples below demonstrate the difference. All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.

Examples

Example 1: Using Pathname

  require 'pathname'
  p = Pathname.new("/usr/bin/ruby")
  size = p.size              # 27662
  isdir = p.directory?       # false
  dir  = p.dirname           # Pathname:/usr/bin
  base = p.basename          # Pathname:ruby
  dir, base = p.split        # [Pathname:/usr/bin, Pathname:ruby]
  data = p.read
  p.open { |f| _ }
  p.each_line { |line| _ }

Example 2: Using standard Ruby

  p = "/usr/bin/ruby"
  size = File.size(p)        # 27662
  isdir = File.directory?(p) # false
  dir  = File.dirname(p)     # "/usr/bin"
  base = File.basename(p)    # "ruby"
  dir, base = File.split(p)  # ["/usr/bin", "ruby"]
  data = File.read(p)
  File.open(p) { |f| _ }
  File.foreach(p) { |line| _ }

Example 3: Special features

  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

These methods are effectively manipulating a String, because that‘s all a path is. Except for mountpoint?, children, and realpath, they don‘t access the filesystem.

File status predicate methods

These methods are a facade for 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

These methods are a facade for File:

Directory methods

These methods are a facade for Dir:

IO

These methods are a facade for IO:

  • each_line(*args, &block)
  • read(*args)
  • readlines(*args)
  • sysopen(*args)

Utilities

These methods are a mixture of Find, FileUtils, and others:

Method documentation

As the above section shows, most of the methods in Pathname are facades. The documentation for these methods generally just says, for instance, "See FileTest.writable?", as you should be familiar with the original method anyway, and its documentation (e.g. through ri) will contain more information. In some cases, a brief description will follow.

Methods

Constants

SEPARATOR_PAT = /[#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}]/
SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/

External Aliases

getwd -> pwd

Public Class methods

See Dir.getwd. Returns the current working directory as a Pathname.

[Source]

     # File lib/pathname.rb, line 955
955:   def Pathname.getwd() self.new(Dir.getwd) end

See Dir.glob. Returns or yields Pathname objects.

[Source]

     # File lib/pathname.rb, line 946
946:   def Pathname.glob(*args) # :yield: p
947:     if block_given?
948:       Dir.glob(*args) {|f| yield self.new(f) }
949:     else
950:       Dir.glob(*args).map {|f| self.new(f) }
951:     end
952:   end

Create a Pathname object from the given String (or String-like object). If path contains a NUL character (\0), an ArgumentError is raised.

[Source]

     # File lib/pathname.rb, line 203
203:   def initialize(path)
204:     path = path.__send__(TO_PATH) if path.respond_to? TO_PATH
205:     @path = path.dup
206: 
207:     if /\0/ =~ @path
208:       raise ArgumentError, "pathname contains \\0: #{@path.inspect}"
209:     end
210: 
211:     self.taint if @path.tainted?
212:   end

Public Instance methods

Pathname#+ appends a pathname fragment to this one to produce a new Pathname object.

  p1 = Pathname.new("/usr")      # Pathname:/usr
  p2 = p1 + "bin/ruby"           # Pathname:/usr/bin/ruby
  p3 = p1 + "/etc/passwd"        # Pathname:/etc/passwd

This method doesn‘t access the file system; it is pure string manipulation.

[Source]

     # File lib/pathname.rb, line 595
595:   def +(other)
596:     other = Pathname.new(other) unless Pathname === other
597:     Pathname.new(plus(@path, other.to_s))
598:   end

Provides for comparing pathnames, case-sensitively.

[Source]

     # File lib/pathname.rb, line 231
231:   def <=>(other)
232:     return nil unless Pathname === other
233:     @path.tr('/', "\0") <=> other.to_s.tr('/', "\0")
234:   end

Compare this pathname with other. The comparison is string-based. Be aware that two different paths (foo.txt and ./foo.txt) can refer to the same file.

[Source]

     # File lib/pathname.rb, line 223
223:   def ==(other)
224:     return false unless Pathname === other
225:     other.to_s == @path
226:   end
===(other)

Alias for #==

TO_PATH()

Alias for to_s

Predicate method for testing whether a path is absolute. It returns true if the pathname begins with a slash.

[Source]

     # File lib/pathname.rb, line 503
503:   def absolute?
504:     !relative?
505:   end

Iterates over and yields a new Pathname object for each element in the given path in ascending order.

 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>

It doesn‘t access actual filesystem.

This method is available since 1.8.5.

[Source]

     # File lib/pathname.rb, line 575
575:   def ascend
576:     path = @path
577:     yield self
578:     while r = chop_basename(path)
579:       path, name = r
580:       break if path.empty?
581:       yield self.class.new(del_trailing_separator(path))
582:     end
583:   end

See File.atime. Returns last access time.

[Source]

     # File lib/pathname.rb, line 776
776:   def atime() File.atime(@path) end

See File.basename. Returns the last component of the path.

[Source]

     # File lib/pathname.rb, line 837
837:   def basename(*args) self.class.new(File.basename(@path, *args)) end

See FileTest.blockdev?.

[Source]

     # File lib/pathname.rb, line 871
871:   def blockdev?() FileTest.blockdev?(@path) end

See FileTest.chardev?.

[Source]

     # File lib/pathname.rb, line 874
874:   def chardev?() FileTest.chardev?(@path) end

Pathname#chdir is obsoleted at 1.8.1.

[Source]

     # File lib/pathname.rb, line 959
959:   def chdir(&block)
960:     warn "Pathname#chdir is obsoleted.  Use Dir.chdir."
961:     Dir.chdir(@path, &block)
962:   end

Returns the children of the directory (files and subdirectories, not recursive) as an array of Pathname objects. By default, the returned pathnames will have enough information to access the files. If you set with_directory to false, then the returned pathnames will contain the filename only.

For example:

  p = Pathname("/usr/lib/ruby/1.8")
  p.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, ... ]
  p.children(false)
      # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]

Note that the result never contain the entries . and .. in the directory because they are not children.

This method has existed since 1.8.1.

[Source]

     # File lib/pathname.rb, line 682
682:   def children(with_directory=true)
683:     with_directory = false if @path == '.'
684:     result = []
685:     Dir.foreach(@path) {|e|
686:       next if e == '.' || e == '..'
687:       if with_directory
688:         result << self.class.new(File.join(@path, e))
689:       else
690:         result << self.class.new(e)
691:       end
692:     }
693:     result
694:   end

See File.chmod. Changes permissions.

[Source]

     # File lib/pathname.rb, line 785
785:   def chmod(mode) File.chmod(mode, @path) end

See File.chown. Change owner and group of file.

[Source]

     # File lib/pathname.rb, line 791
791:   def chown(owner, group) File.chown(owner, group, @path) end

Pathname#chroot is obsoleted at 1.8.1.

[Source]

     # File lib/pathname.rb, line 965
965:   def chroot
966:     warn "Pathname#chroot is obsoleted.  Use Dir.chroot."
967:     Dir.chroot(@path)
968:   end

Returns clean pathname of self with consecutive slashes and useless dots removed. The filesystem is not accessed.

If consider_symlink is true, then a more conservative algorithm is used to avoid breaking symbolic linkages. This may retain more .. entries than absolutely necessary, but without accessing the filesystem, this can‘t be avoided. See realpath.

[Source]

     # File lib/pathname.rb, line 320
320:   def cleanpath(consider_symlink=false)
321:     if consider_symlink
322:       cleanpath_conservative
323:     else
324:       cleanpath_aggressive
325:     end
326:   end

See File.ctime. Returns last (directory entry, not file) change time.

[Source]

     # File lib/pathname.rb, line 779
779:   def ctime() File.ctime(@path) end
delete()

Alias for unlink

Iterates over and yields a new Pathname object for each element in the given path in descending order.

 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>

It doesn‘t access actual filesystem.

This method is available since 1.8.5.

[Source]

     # File lib/pathname.rb, line 548
548:   def descend
549:     vs = []
550:     ascend {|v| vs << v }
551:     vs.reverse_each {|v| yield v }
552:     nil
553:   end

Pathname#dir_foreach is obsoleted at 1.8.1.

[Source]

     # File lib/pathname.rb, line 983
983:   def dir_foreach(*args, &block)
984:     warn "Pathname#dir_foreach is obsoleted.  Use Pathname#each_entry."
985:     each_entry(*args, &block)
986:   end

See FileTest.directory?.

[Source]

     # File lib/pathname.rb, line 889
889:   def directory?() FileTest.directory?(@path) end

See File.dirname. Returns all but the last component of the path.

[Source]

     # File lib/pathname.rb, line 840
840:   def dirname() self.class.new(File.dirname(@path)) end

Iterates over the entries (files and subdirectories) in the directory. It yields a Pathname object for each entry.

This method has existed since 1.8.1.

[Source]

     # File lib/pathname.rb, line 978
978:   def each_entry(&block) # :yield: p
979:     Dir.foreach(@path) {|f| yield self.class.new(f) }
980:   end

Iterates over each component of the path.

  Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
    # yields "usr", "bin", and "ruby".

[Source]

     # File lib/pathname.rb, line 522
522:   def each_filename # :yield: filename
523:     prefix, names = split_names(@path)
524:     names.each {|filename| yield filename }
525:     nil
526:   end

each_line iterates over the line in the file. It yields a String object for each line.

This method has existed since 1.8.1.

[Source]

     # File lib/pathname.rb, line 751
751:   def each_line(*args, &block) # :yield: line
752:     IO.foreach(@path, *args, &block)
753:   end

Return the entries (files and subdirectories) in the directory, each as a Pathname object.

[Source]

     # File lib/pathname.rb, line 972
972:   def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
eql?(other)

Alias for #==

See FileTest.executable?.

[Source]

     # File lib/pathname.rb, line 877
877:   def executable?() FileTest.executable?(@path) end

See FileTest.executable_real?.

[Source]

     # File lib/pathname.rb, line 880
880:   def executable_real?() FileTest.executable_real?(@path) end

See FileTest.exist?.

[Source]

     # File lib/pathname.rb, line 883
883:   def exist?() FileTest.exist?(@path) end

See File.expand_path.

[Source]

     # File lib/pathname.rb, line 846
846:   def expand_path(*args) self.class.new(File.expand_path(@path, *args)) end

See File.extname. Returns the file‘s extension.

[Source]

     # File lib/pathname.rb, line 843
843:   def extname() File.extname(@path) end

See FileTest.file?.

[Source]

     # File lib/pathname.rb, line 892
892:   def file?() FileTest.file?(@path) end

Pathname#find is an iterator to traverse a directory tree in a depth first manner. It yields a Pathname for each file under "this" directory.

Since it is implemented by find.rb, Find.prune can be used to control the traverse.

If self is ., yielded pathnames begin with a filename in the current directory, not ./.

[Source]

      # File lib/pathname.rb, line 1012
1012:   def find(&block) # :yield: p
1013:     require 'find'
1014:     if @path == '.'
1015:       Find.find(@path) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
1016:     else
1017:       Find.find(@path) {|f| yield self.class.new(f) }
1018:     end
1019:   end

See File.fnmatch. Return true if the receiver matches the given pattern.

[Source]

     # File lib/pathname.rb, line 798
798:   def fnmatch(pattern, *args) File.fnmatch(pattern, @path, *args) end

See File.fnmatch? (same as fnmatch).

[Source]

     # File lib/pathname.rb, line 801
801:   def fnmatch?(pattern, *args) File.fnmatch?(pattern, @path, *args) end

This method is obsoleted at 1.8.1. Use each_line or each_entry.

[Source]

      # File lib/pathname.rb, line 1056
1056:   def foreach(*args, &block)
1057:     warn "Pathname#foreach is obsoleted.  Use each_line or each_entry."
1058:     if FileTest.directory? @path
1059:       # For polymorphism between Dir.foreach and IO.foreach,
1060:       # Pathname#foreach doesn't yield Pathname object.
1061:       Dir.foreach(@path, *args, &block)
1062:     else
1063:       IO.foreach(@path, *args, &block)
1064:     end
1065:   end

Pathname#foreachline is obsoleted at 1.8.1. Use each_line.

[Source]

     # File lib/pathname.rb, line 756
756:   def foreachline(*args, &block)
757:     warn "Pathname#foreachline is obsoleted.  Use Pathname#each_line."
758:     each_line(*args, &block)
759:   end

[Source]

     # File lib/pathname.rb, line 214
214:   def freeze() super; @path.freeze; self end

See File.ftype. Returns "type" of file ("file", "directory", etc).

[Source]

     # File lib/pathname.rb, line 805
805:   def ftype() File.ftype(@path) end

See FileTest.grpowned?.

[Source]

     # File lib/pathname.rb, line 886
886:   def grpowned?() FileTest.grpowned?(@path) end

Pathname#join joins pathnames.

path0.join(path1, …, pathN) is the same as path0 + path1 + … + pathN.

[Source]

     # File lib/pathname.rb, line 648
648:   def join(*args)
649:     args.unshift self
650:     result = args.pop
651:     result = Pathname.new(result) unless Pathname === result
652:     return result if result.absolute?
653:     args.reverse_each {|arg|
654:       arg = Pathname.new(arg) unless Pathname === arg
655:       result = arg + result
656:       return result if result.absolute?
657:     }
658:     result
659:   end

See File.lchmod.

[Source]

     # File lib/pathname.rb, line 788
788:   def lchmod(mode) File.lchmod(mode, @path) end

See File.lchown.

[Source]

     # File lib/pathname.rb, line 794
794:   def lchown(owner, group) File.lchown(owner, group, @path) end

Pathname#link is confusing and obsoleted because the receiver/argument order is inverted to corresponding system call.

[Source]

     # File lib/pathname.rb, line 854
854:   def link(old)
855:     warn 'Pathname#link is obsoleted.  Use Pathname#make_link.'
856:     File.link(old, @path)
857:   end

See File.lstat.

[Source]

     # File lib/pathname.rb, line 825
825:   def lstat() File.lstat(@path) end

See File.link. Creates a hard link.

[Source]

     # File lib/pathname.rb, line 808
808:   def make_link(old) File.link(old, @path) end

See File.symlink. Creates a symbolic link.

[Source]

     # File lib/pathname.rb, line 828
828:   def make_symlink(old) File.symlink(old, @path) end

See Dir.mkdir. Create the referenced directory.

[Source]

     # File lib/pathname.rb, line 989
989:   def mkdir(*args) Dir.mkdir(@path, *args) end

See FileUtils.mkpath. Creates a full path, including any intermediate directories that don‘t yet exist.

[Source]

      # File lib/pathname.rb, line 1026
1026:   def mkpath
1027:     require 'fileutils'
1028:     FileUtils.mkpath(@path)
1029:     nil
1030:   end

mountpoint? returns true if self points to a mountpoint.

[Source]

     # File lib/pathname.rb, line 479
479:   def mountpoint?
480:     begin
481:       stat1 = self.lstat
482:       stat2 = self.parent.lstat
483:       stat1.dev == stat2.dev && stat1.ino == stat2.ino ||
484:         stat1.dev != stat2.dev
485:     rescue Errno::ENOENT
486:       false
487:     end
488:   end

See File.mtime. Returns last modification time.

[Source]

     # File lib/pathname.rb, line 782
782:   def mtime() File.mtime(@path) end

See File.open. Opens the file for reading or writing.

[Source]

     # File lib/pathname.rb, line 811
811:   def open(*args, &block) # :yield: file
812:     File.open(@path, *args, &block)
813:   end

See Dir.open.

[Source]

     # File lib/pathname.rb, line 995
995:   def opendir(&block) # :yield: dir
996:     Dir.open(@path, &block)
997:   end

See FileTest.owned?.

[Source]

     # File lib/pathname.rb, line 901
901:   def owned?() FileTest.owned?(@path) end

parent returns the parent directory.

This is same as self + ’..’.

[Source]

     # File lib/pathname.rb, line 474
474:   def parent
475:     self + '..'
476:   end

See FileTest.pipe?.

[Source]

     # File lib/pathname.rb, line 895
895:   def pipe?() FileTest.pipe?(@path) end

See IO.read. Returns all the bytes from the file, or the first N if specified.

[Source]

     # File lib/pathname.rb, line 763
763:   def read(*args) IO.read(@path, *args) end

See FileTest.readable?.

[Source]

     # File lib/pathname.rb, line 904
904:   def readable?() FileTest.readable?(@path) end

See FileTest.readable_real?.

[Source]

     # File lib/pathname.rb, line 910
910:   def readable_real?() FileTest.readable_real?(@path) end

See IO.readlines. Returns all the lines from the file.

[Source]

     # File lib/pathname.rb, line 766
766:   def readlines(*args) IO.readlines(@path, *args) end

See File.readlink. Read symbolic link.

[Source]

     # File lib/pathname.rb, line 816
816:   def readlink() self.class.new(File.readlink(@path)) end

Returns a real (absolute) pathname of self in the actual filesystem. The real pathname doesn‘t contain symlinks or useless dots.

No arguments should be given; the old behaviour is obsoleted.

[Source]

     # File lib/pathname.rb, line 460
460:   def realpath
461:     path = @path
462:     prefix, names = split_names(path)
463:     if prefix == ''
464:       prefix, names2 = split_names(Dir.pwd)
465:       names = names2 + names
466:     end
467:     prefix, *names = realpath_rec(prefix, names, {})
468:     self.class.new(prepend_prefix(prefix, File.join(*names)))
469:   end

The opposite of absolute?

[Source]

     # File lib/pathname.rb, line 508
508:   def relative?
509:     path = @path
510:     while r = chop_basename(path)
511:       path, basename = r
512:     end
513:     path == ''
514:   end

relative_path_from returns a relative path from the argument to the receiver. If self is absolute, the argument must be absolute too. If self is relative, the argument must be relative too.

relative_path_from doesn‘t access the filesystem. It assumes no symlinks.

ArgumentError is raised when it cannot find a relative path.

This method has existed since 1.8.1.

[Source]

     # File lib/pathname.rb, line 707
707:   def relative_path_from(base_directory)
708:     dest_directory = self.cleanpath.to_s
709:     base_directory = base_directory.cleanpath.to_s
710:     dest_prefix = dest_directory
711:     dest_names = []
712:     while r = chop_basename(dest_prefix)
713:       dest_prefix, basename = r
714:       dest_names.unshift basename if basename != '.'
715:     end
716:     base_prefix = base_directory
717:     base_names = []
718:     while r = chop_basename(base_prefix)
719:       base_prefix, basename = r
720:       base_names.unshift basename if basename != '.'
721:     end
722:     if dest_prefix != base_prefix
723:       raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
724:     end
725:     while !dest_names.empty? &&
726:           !base_names.empty? &&
727:           dest_names.first == base_names.first
728:       dest_names.shift
729:       base_names.shift
730:     end
731:     if base_names.include? '..'
732:       raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
733:     end
734:     base_names.fill('..')
735:     relpath_names = base_names + dest_names
736:     if relpath_names.empty?
737:       Pathname.new('.')
738:     else
739:       Pathname.new(File.join(*relpath_names))
740:     end
741:   end

See File.rename. Rename the file.

[Source]

     # File lib/pathname.rb, line 819
819:   def rename(to) File.rename(@path, to) end

See Dir.rmdir. Remove the referenced directory.

[Source]

     # File lib/pathname.rb, line 992
992:   def rmdir() Dir.rmdir(@path) end

See FileUtils.rm_r. Deletes a directory and all beneath it.

[Source]

      # File lib/pathname.rb, line 1033
1033:   def rmtree
1034:     # The name "rmtree" is borrowed from File::Path of Perl.
1035:     # File::Path provides "mkpath" and "rmtree".
1036:     require 'fileutils'
1037:     FileUtils.rm_r(@path)
1038:     nil
1039:   end

root? is a predicate for root directories. I.e. it returns true if the pathname consists of consecutive slashes.

It doesn‘t access actual filesystem. So it may return false for some pathnames which points to roots such as /usr/...

[Source]

     # File lib/pathname.rb, line 497
497:   def root?
498:     !!(chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o =~ @path)
499:   end

See FileTest.setgid?.

[Source]

     # File lib/pathname.rb, line 916
916:   def setgid?() FileTest.setgid?(@path) end

See FileTest.setuid?.

[Source]

     # File lib/pathname.rb, line 913
913:   def setuid?() FileTest.setuid?(@path) end

See FileTest.size.

[Source]

     # File lib/pathname.rb, line 919
919:   def size() FileTest.size(@path) end

See FileTest.size?.

[Source]

     # File lib/pathname.rb, line 922
922:   def size?() FileTest.size?(@path) end

See FileTest.socket?.

[Source]

     # File lib/pathname.rb, line 898
898:   def socket?() FileTest.socket?(@path) end

See File.split. Returns the dirname and the basename in an Array.

[Source]

     # File lib/pathname.rb, line 850
850:   def split() File.split(@path).map {|f| self.class.new(f) } end

See File.stat. Returns a File::Stat object.

[Source]

     # File lib/pathname.rb, line 822
822:   def stat() File.stat(@path) end

See FileTest.sticky?.

[Source]

     # File lib/pathname.rb, line 925
925:   def sticky?() FileTest.sticky?(@path) end

Return a pathname which is substituted by String#sub.

[Source]

     # File lib/pathname.rb, line 253
253:   def sub(pattern, *rest, &block)
254:     if block
255:       path = @path.sub(pattern, *rest) {|*args|
256:         begin
257:           old = Thread.current[:pathname_sub_matchdata]
258:           Thread.current[:pathname_sub_matchdata] = $~
259:           eval("$~ = Thread.current[:pathname_sub_matchdata]", block.binding)
260:         ensure
261:           Thread.current[:pathname_sub_matchdata] = old
262:         end
263:         yield *args
264:       }
265:     else
266:       path = @path.sub(pattern, *rest)
267:     end
268:     self.class.new(path)
269:   end

Pathname#symlink is confusing and obsoleted because the receiver/argument order is inverted to corresponding system call.

[Source]

     # File lib/pathname.rb, line 861
861:   def symlink(old)
862:     warn 'Pathname#symlink is obsoleted.  Use Pathname#make_symlink.'
863:     File.symlink(old, @path)
864:   end

See FileTest.symlink?.

[Source]

     # File lib/pathname.rb, line 928
928:   def symlink?() FileTest.symlink?(@path) end

See IO.sysopen.

[Source]

     # File lib/pathname.rb, line 769
769:   def sysopen(*args) IO.sysopen(@path, *args) end

[Source]

     # File lib/pathname.rb, line 215
215:   def taint() super; @path.taint; self end

Return the path as a String.

[Source]

     # File lib/pathname.rb, line 241
241:   def to_s
242:     @path.dup
243:   end

See File.truncate. Truncate the file to length bytes.

[Source]

     # File lib/pathname.rb, line 831
831:   def truncate(length) File.truncate(@path, length) end

Removes a file or directory, using File.unlink or Dir.unlink as necessary.

[Source]

      # File lib/pathname.rb, line 1046
1046:   def unlink()
1047:     begin
1048:       Dir.unlink @path
1049:     rescue Errno::ENOTDIR
1050:       File.unlink @path
1051:     end
1052:   end

[Source]

     # File lib/pathname.rb, line 216
216:   def untaint() super; @path.untaint; self end

See File.utime. Update the access and modification times.

[Source]

     # File lib/pathname.rb, line 834
834:   def utime(atime, mtime) File.utime(atime, mtime, @path) end

See FileTest.world_readable?.

[Source]

     # File lib/pathname.rb, line 907
907:   def world_readable?() FileTest.world_readable?(@path) end

See FileTest.world_writable?.

[Source]

     # File lib/pathname.rb, line 934
934:   def world_writable?() FileTest.world_writable?(@path) end

See FileTest.writable?.

[Source]

     # File lib/pathname.rb, line 931
931:   def writable?() FileTest.writable?(@path) end

See FileTest.writable_real?.

[Source]

     # File lib/pathname.rb, line 937
937:   def writable_real?() FileTest.writable_real?(@path) end

See FileTest.zero?.

[Source]

     # File lib/pathname.rb, line 940
940:   def zero?() FileTest.zero?(@path) end

Private Instance methods

add_trailing_separator(path) -> path

[Source]

     # File lib/pathname.rb, line 369
369:   def add_trailing_separator(path)
370:     if File.basename(path + 'a') == 'a'
371:       path
372:     else
373:       File.join(path, "") # xxx: Is File.join is appropriate to add separator?
374:     end
375:   end

chop_basename(path) -> [pre-basename, basename] or nil

[Source]

     # File lib/pathname.rb, line 278
278:   def chop_basename(path)
279:     base = File.basename(path)
280:     if /\A#{SEPARATOR_PAT}?\z/ =~ base
281:       return nil
282:     else
283:       return path[0, path.rindex(base)], base
284:     end
285:   end

Clean the path simply by resolving and removing excess "." and ".." entries. Nothing more, nothing less.

[Source]

     # File lib/pathname.rb, line 332
332:   def cleanpath_aggressive
333:     path = @path
334:     names = []
335:     pre = path
336:     while r = chop_basename(pre)
337:       pre, base = r
338:       case base
339:       when '.'
340:       when '..'
341:         names.unshift base
342:       else
343:         if names[0] == '..'
344:           names.shift
345:         else
346:           names.unshift base
347:         end
348:       end
349:     end
350:     if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
351:       names.shift while names[0] == '..'
352:     end
353:     self.class.new(prepend_prefix(pre, File.join(*names)))
354:   end

[Source]

     # File lib/pathname.rb, line 390
390:   def cleanpath_conservative
391:     path = @path
392:     names = []
393:     pre = path
394:     while r = chop_basename(pre)
395:       pre, base = r
396:       names.unshift base if base != '.'
397:     end
398:     if /#{SEPARATOR_PAT}/o =~ File.basename(pre)
399:       names.shift while names[0] == '..'
400:     end
401:     if names.empty?
402:       self.class.new(File.dirname(pre))
403:     else
404:       if names.last != '..' && File.basename(path) == '.'
405:         names << '.'
406:       end
407:       result = prepend_prefix(pre, File.join(*names))
408:       if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path)
409:         self.class.new(add_trailing_separator(result))
410:       else
411:         self.class.new(result)
412:       end
413:     end
414:   end

[Source]

     # File lib/pathname.rb, line 378
378:   def del_trailing_separator(path)
379:     if r = chop_basename(path)
380:       pre, basename = r
381:       pre + basename
382:     elsif /#{SEPARATOR_PAT}+\z/o =~ path
383:       $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o]
384:     else
385:       path
386:     end
387:   end

has_trailing_separator?(path) -> bool

[Source]

     # File lib/pathname.rb, line 358
358:   def has_trailing_separator?(path)
359:     if r = chop_basename(path)
360:       pre, basename = r
361:       pre.length + basename.length < path.length
362:     else
363:       false
364:     end
365:   end

[Source]

     # File lib/pathname.rb, line 600
600:   def plus(path1, path2) # -> path
601:     prefix2 = path2
602:     index_list2 = []
603:     basename_list2 = []
604:     while r2 = chop_basename(prefix2)
605:       prefix2, basename2 = r2
606:       index_list2.unshift prefix2.length
607:       basename_list2.unshift basename2
608:     end
609:     return path2 if prefix2 != ''
610:     prefix1 = path1
611:     while true
612:       while !basename_list2.empty? && basename_list2.first == '.'
613:         index_list2.shift
614:         basename_list2.shift
615:       end
616:       break unless r1 = chop_basename(prefix1)
617:       prefix1, basename1 = r1
618:       next if basename1 == '.'
619:       if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..'
620:         prefix1 = prefix1 + basename1
621:         break
622:       end
623:       index_list2.shift
624:       basename_list2.shift
625:     end
626:     r1 = chop_basename(prefix1)
627:     if !r1 && /#{SEPARATOR_PAT}/o =~ File.basename(prefix1)
628:       while !basename_list2.empty? && basename_list2.first == '..'
629:         index_list2.shift
630:         basename_list2.shift
631:       end
632:     end
633:     if !basename_list2.empty?
634:       suffix2 = path2[index_list2.first..-1]
635:       r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2
636:     else
637:       r1 ? prefix1 : File.dirname(prefix1)
638:     end
639:   end

[Source]

     # File lib/pathname.rb, line 299
299:   def prepend_prefix(prefix, relpath)
300:     if relpath.empty?
301:       File.dirname(prefix)
302:     elsif /#{SEPARATOR_PAT}/ =~ prefix
303:       prefix = File.dirname(prefix)
304:       prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
305:       prefix + relpath
306:     else
307:       prefix + relpath
308:     end
309:   end

[Source]

     # File lib/pathname.rb, line 417
417:   def realpath_rec(prefix, unresolved, h)
418:     resolved = []
419:     until unresolved.empty?
420:       n = unresolved.shift
421:       if n == '.'
422:         next
423:       elsif n == '..'
424:         resolved.pop
425:       else
426:         path = prepend_prefix(prefix, File.join(*(resolved + [n])))
427:         if h.include? path
428:           if h[path] == :resolving
429:             raise Errno::ELOOP.new(path)
430:           else
431:             prefix, *resolved = h[path]
432:           end
433:         else
434:           s = File.lstat(path)
435:           if s.symlink?
436:             h[path] = :resolving
437:             link_prefix, link_names = split_names(File.readlink(path))
438:             if link_prefix == ''
439:               prefix, *resolved = h[path] = realpath_rec(prefix, resolved + link_names, h)
440:             else
441:               prefix, *resolved = h[path] = realpath_rec(link_prefix, link_names, h)
442:             end
443:           else
444:             resolved << n
445:             h[path] = [prefix, *resolved]
446:           end
447:         end
448:       end
449:     end
450:     return prefix, *resolved
451:   end

split_names(path) -> prefix, [name, …]

[Source]

     # File lib/pathname.rb, line 289
289:   def split_names(path)
290:     names = []
291:     while r = chop_basename(path)
292:       path, basename = r
293:       names.unshift basename
294:     end
295:     return path, names
296:   end

[Validate]