# class Pathname

`Pathname` represents the name of a file or directory on the filesystem, but not the file itself.

The pathname depends on the Operating System: Unix, Windows, etc. This library works with pathnames of local OS, however non-Unix pathnames are supported experimentally.

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 goal 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'
    pn = Pathname.new("/usr/bin/ruby")
    size = pn.size              # 27662
    isdir = pn.directory?       # false
    dir  = pn.dirname           # Pathname:/usr/bin
    base = pn.basename          # Pathname:ruby
    dir, base = pn.split        # [Pathname:/usr/bin, Pathname:ruby]
    data = pn.read
    pn.open { |f| _ }
    pn.each_line { |line| _ }

### Example 2: Using standard Ruby¶ ↑

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

### 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. None of these access the file system except for `mountpoint?`, `children`, `each_child`, `realdirpath` and `realpath`.

- +

- `join`

- `parent`

- `root?`

- `absolute?`

- `relative?`

- `relative_path_from`

- `each_filename`

- `cleanpath`

- `realpath`

- `realdirpath`

- `children`

- `each_child`

- `mountpoint?`

### `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:

- `atime`

- `birthtime`

- `ctime`

- `mtime`

- `chmod(mode)`

- `lchmod(mode)`

- `chown`(owner, group)

- `lchown`(owner, group)

- `fnmatch`(pattern, *args)

- `fnmatch?`(pattern, *args)

- `ftype`

- `make_link(old)`

- `open`(*args, &block)

- `readlink`

- `rename(to)`

- `stat`

- `lstat`

- `make_symlink(old)`

- `truncate(length)`

- `utime`(atime, mtime)

- `basename(*args)`

- `dirname`

- `extname`

- `expand_path(*args)`

- `split`

### Directory methods¶ ↑

These methods are a facade for Dir:

- `Pathname.glob(*args)`

- `Pathname.getwd` / `Pathname.pwd`

- `rmdir`

- `entries`

- `each_entry`(&block)

- `mkdir(*args)`

- `opendir(*args)`

### `IO`¶ ↑

These methods are a facade for IO:

- `each_line`(*args, &block)

- `read(*args)`

- `binread(*args)`

- `readlines(*args)`

- `sysopen(*args)`

- `write(*args)`

- `binwrite(*args)`

### Utilities¶ ↑

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

- `find`(&block)

- `mkpath`

- `rmtree`

- `unlink` / `delete`

## `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.

### Public Class Methods

getwd() click to toggle source

Returns the current working directory as a `Pathname`.

    Pathname.getwd
        #=> #<Pathname:/home/zzak/projects/ruby>

See `Dir.getwd`.

    static VALUE
    path_s_getwd(VALUE klass)
    {
        VALUE str;
        str = rb_funcall(rb_cDir, id_getwd, 0);
        return rb_class_new_instance(1, &str, klass);
    }

glob(p1, p2 = v2, p3 = v3) click to toggle source

Returns or yields `Pathname` objects.

    Pathname.glob("lib/i*.rb")
        #=> [#<Pathname:lib/ipaddr.rb>, #<Pathname:lib/irb.rb>]

See `Dir.glob`.

    static VALUE
    path_s_glob(int argc, VALUE *argv, VALUE klass)
    {
        VALUE args[3];
        int n;

        n = rb_scan_args(argc, argv, "12", &args[0], &args[1], &args[2]);
        if (rb_block_given_p()) {
            return rb_block_call_kw(rb_cDir, id_glob, n, args, s_glob_i, klass, RB_PASS_CALLED_KEYWORDS);
        }
        else {
            VALUE ary;
            long i;
            ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_CALLED_KEYWORDS);
            ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
            for (i = 0; i < RARRAY_LEN(ary); i++) {
                VALUE elt = RARRAY_AREF(ary, i);
                elt = rb_class_new_instance(1, &elt, klass);
                rb_ary_store(ary, i, elt);
            }
            return ary;
        }
    }

new(p1) click to toggle source

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

    static VALUE
    path_initialize(VALUE self, VALUE arg)
    {
        VALUE str;
        if (RB_TYPE_P(arg, T_STRING)) {
            str = arg;
        }
        else {
            str = rb_check_funcall(arg, id_to_path, 0, NULL);
            if (str == Qundef)
                str = arg;
            StringValue(str);
        }
        if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str)))
            rb_raise(rb_eArgError, "pathname contains null byte");
        str = rb_obj_dup(str);

        set_strpath(self, str);
        return self;
    }

pwd() click to toggle source

Returns the current working directory as a `Pathname`.

    Pathname.getwd
        #=> #<Pathname:/home/zzak/projects/ruby>

See `Dir.getwd`.

    static VALUE
    path_s_getwd(VALUE klass)
    {
        VALUE str;
        str = rb_funcall(rb_cDir, id_getwd, 0);
        return rb_class_new_instance(1, &str, klass);
    }

### Public Instance Methods

+(other) click to toggle source

Appends a pathname fragment to `self` 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

    # / is aliased to +.
    p4 = p1 / "bin/ruby"           # Pathname:/usr/bin/ruby
    p5 = p1 / "/etc/passwd"        # Pathname:/etc/passwd

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

    # File ext/pathname/lib/pathname.rb, line 352
    def +(other)
      other = Pathname.new(other) unless Pathname === other
      Pathname.new(plus(@path, other.to_s))
    end

Also aliased as: /
/(other)
Alias for: +
<=>(p1) click to toggle source

Provides a case-sensitive comparison operator for pathnames.

    Pathname.new('/usr') <=> Pathname.new('/usr/bin')
        #=> -1
    Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin')
        #=> 0
    Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN')
        #=> 1

It will return `-1`, `0` or `1` depending on the value of the left argument relative to the right argument. Or it will return `nil` if the arguments are not comparable.

    static VALUE
    path_cmp(VALUE self, VALUE other)
    {
        VALUE s1, s2;
        char *p1, *p2;
        char *e1, *e2;
        if (!rb_obj_is_kind_of(other, rb_cPathname))
            return Qnil;
        s1 = get_strpath(self);
        s2 = get_strpath(other);
        p1 = RSTRING_PTR(s1);
        p2 = RSTRING_PTR(s2);
        e1 = p1 + RSTRING_LEN(s1);
        e2 = p2 + RSTRING_LEN(s2);
        while (p1 < e1 && p2 < e2) {
            int c1, c2;
            c1 = (unsigned char)*p1++;
            c2 = (unsigned char)*p2++;
            if (c1 == '/') c1 = '\0';
            if (c2 == '/') c2 = '\0';
            if (c1 != c2) {
                if (c1 < c2)
                    return INT2FIX(-1);
                else
                    return INT2FIX(1);
            }
        }
        if (p1 < e1)
            return INT2FIX(1);
        if (p2 < e2)
            return INT2FIX(-1);
        return INT2FIX(0);
    }

==(p1) click to toggle source

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.

    static VALUE
    path_eq(VALUE self, VALUE other)
    {
        if (!rb_obj_is_kind_of(other, rb_cPathname))
            return Qfalse;
        return rb_str_equal(get_strpath(self), get_strpath(other));
    }

Also aliased as: ===, eql?
===(p1)

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.

Alias for: ==
absolute?() click to toggle source

Predicate method for testing whether a path is absolute.

It returns `true` if the pathname begins with a slash.

    p = Pathname.new('/im/sure')
    p.absolute?
        #=> true

    p = Pathname.new('not/so/sure')
    p.absolute?
        #=> false

    # File ext/pathname/lib/pathname.rb, line 231
    def absolute?
      ABSOLUTE_PATH.match? @path
    end

ascend() { |self| ... } click to toggle source

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>

Returns an `Enumerator` if no block was given.

    enum = Pathname.new("/usr/bin/ruby").ascend
      # ... do stuff ...
    enum.each { |e| ... }
      # yields Pathnames /usr/bin/ruby, /usr/bin, /usr, and /.

It doesn’t access the filesystem.

    # File ext/pathname/lib/pathname.rb, line 328
    def ascend
      return to_enum(__method__) unless block_given?
      path = @path
      yield self
      while r = chop_basename(path)
        path, = r
        break if path.empty?
        yield self.class.new(del_trailing_separator(path))
      end
    end

atime → time click to toggle source

Returns the last access time for the file.

See `File.atime`.

    static VALUE
    path_atime(VALUE self)
    {
        return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
    }

basename(p1 = v1) click to toggle source

Returns the last component of the path.

See `File.basename`.

    static VALUE
    path_basename(int argc, VALUE *argv, VALUE self)
    {
        VALUE str = get_strpath(self);
        VALUE fext;
        if (rb_scan_args(argc, argv, "01", &fext) == 0)
            str = rb_funcall(rb_cFile, id_basename, 1, str);
        else
            str = rb_funcall(rb_cFile, id_basename, 2, str, fext);
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

binread([length [, offset]]) → string click to toggle source

Returns all the bytes from the file, or the first `N` if specified.

See `File.binread`.

    static VALUE
    path_binread(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[3];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
        return rb_funcallv(rb_cFile, id_binread, 1+n, args);
    }

binwrite(string, [offset] ) → fixnum click to toggle source
binwrite(string, [offset], open_args ) → fixnum

Writes `contents` to the file, opening it in binary mode.

See `File.binwrite`.

    static VALUE
    path_binwrite(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[4];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
        return rb_funcallv_kw(rb_cFile, id_binwrite, 1+n, args, RB_PASS_CALLED_KEYWORDS);
    }

birthtime → time click to toggle source

Returns the birth time for the file. If the platform doesn’t have birthtime, raises `NotImplementedError`.

See `File.birthtime`.

    static VALUE
    path_birthtime(VALUE self)
    {
        return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
    }

blockdev?() click to toggle source

See `FileTest.blockdev?`.

    static VALUE
    path_blockdev_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_blockdev_p, 1, get_strpath(self));
    }

chardev?() click to toggle source

See `FileTest.chardev?`.

    static VALUE
    path_chardev_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_chardev_p, 1, get_strpath(self));
    }

children(with_directory=true) click to toggle source

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:

    pn = Pathname("/usr/lib/ruby/1.8")
    pn.children
        # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
               Pathname:/usr/lib/ruby/1.8/Env.rb,
               Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
    pn.children(false)
        # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]

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

    # File ext/pathname/lib/pathname.rb, line 443
    def children(with_directory=true)
      with_directory = false if @path == '.'
      result = []
      Dir.foreach(@path) {|e|
        next if e == '.' || e == '..'
        if with_directory
          result << self.class.new(File.join(@path, e))
        else
          result << self.class.new(e)
        end
      }
      result
    end

chmod(mode_int) → integer click to toggle source

Changes file permissions.

See `File.chmod`.

    static VALUE
    path_chmod(VALUE self, VALUE mode)
    {
        return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self));
    }

chown(owner_int, group_int) → integer click to toggle source

Change owner and group of the file.

See `File.chown`.

    static VALUE
    path_chown(VALUE self, VALUE owner, VALUE group)
    {
        return rb_funcall(rb_cFile, id_chown, 3, owner, group, get_strpath(self));
    }

cleanpath(consider_symlink=false) click to toggle source

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 `Pathname#realpath`.

    # File ext/pathname/lib/pathname.rb, line 92
    def cleanpath(consider_symlink=false)
      if consider_symlink
        cleanpath_conservative
      else
        cleanpath_aggressive
      end
    end

ctime → time click to toggle source

Returns the last change time, using directory information, not the file itself.

See `File.ctime`.

    static VALUE
    path_ctime(VALUE self)
    {
        return rb_funcall(rb_cFile, id_ctime, 1, get_strpath(self));
    }

delete()

Removes a file or directory, using `File.unlink` if `self` is a file, or `Dir.unlink` as necessary.

Alias for: unlink
descend() { |v| ... } click to toggle source

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>

Returns an `Enumerator` if no block was given.

    enum = Pathname.new("/usr/bin/ruby").descend
      # ... do stuff ...
    enum.each { |e| ... }
      # yields Pathnames /, /usr, /usr/bin, and /usr/bin/ruby.

It doesn’t access the filesystem.

    # File ext/pathname/lib/pathname.rb, line 295
    def descend
      return to_enum(__method__) unless block_given?
      vs = []
      ascend {|v| vs << v }
      vs.reverse_each {|v| yield v }
      nil
    end

directory?() click to toggle source

See `FileTest.directory?`.

    static VALUE
    path_directory_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_directory_p, 1, get_strpath(self));
    }

dirname() click to toggle source

Returns all but the last component of the path.

See `File.dirname`.

    static VALUE
    path_dirname(VALUE self)
    {
        VALUE str = get_strpath(self);
        str = rb_funcall(rb_cFile, id_dirname, 1, str);
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

each_child(with_directory=true, &b) click to toggle source

Iterates over the children of the directory (files and subdirectories, not recursive).

It yields `Pathname` object for each child.

By default, the yielded 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.

    Pathname("/usr/local").each_child {|f| p f }
    #=> #<Pathname:/usr/local/share>
    #   #<Pathname:/usr/local/bin>
    #   #<Pathname:/usr/local/games>
    #   #<Pathname:/usr/local/lib>
    #   #<Pathname:/usr/local/include>
    #   #<Pathname:/usr/local/sbin>
    #   #<Pathname:/usr/local/src>
    #   #<Pathname:/usr/local/man>

    Pathname("/usr/local").each_child(false) {|f| p f }
    #=> #<Pathname:share>
    #   #<Pathname:bin>
    #   #<Pathname:games>
    #   #<Pathname:lib>
    #   #<Pathname:include>
    #   #<Pathname:sbin>
    #   #<Pathname:src>
    #   #<Pathname:man>

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

See `Pathname#children`

    # File ext/pathname/lib/pathname.rb, line 493
    def each_child(with_directory=true, &b)
      children(with_directory).each(&b)
    end

each_entry() click to toggle source

Iterates over the entries (files and subdirectories) in the directory, yielding a `Pathname` object for each entry.

    static VALUE
    path_each_entry(VALUE self)
    {
        VALUE args[1];

        args[0] = get_strpath(self);
        return rb_block_call(rb_cDir, id_foreach, 1, args, each_entry_i, rb_obj_class(self));
    }

each_filename() { |filename| ... } click to toggle source

Iterates over each component of the path.

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

Returns an `Enumerator` if no block was given.

    enum = Pathname.new("/usr/bin/ruby").each_filename
      # ... do stuff ...
    enum.each { |e| ... }
      # yields "usr", "bin", and "ruby".

    # File ext/pathname/lib/pathname.rb, line 263
    def each_filename # :yield: filename
      return to_enum(__method__) unless block_given?
      _, names = split_names(@path)
      names.each {|filename| yield filename }
      nil
    end

each_line {|line| ... } click to toggle source
each_line(sep=$/ [, open_args]) {|line| block } → nil
each_line(limit [, open_args]) {|line| block } → nil
each_line(sep, limit [, open_args]) {|line| block } → nil
each_line(...) → an_enumerator

Iterates over each line in the file and yields a `String` object for each.

    static VALUE
    path_each_line(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[4];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
        if (rb_block_given_p()) {
            return rb_block_call_kw(rb_cFile, id_foreach, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
        }
        else {
            return rb_funcallv_kw(rb_cFile, id_foreach, 1+n, args, RB_PASS_CALLED_KEYWORDS);
        }
    }

empty?() click to toggle source

Tests the file is empty.

See Dir#empty? and `FileTest.empty?`.

    static VALUE
    path_empty_p(VALUE self)
    {

        VALUE path = get_strpath(self);
        if (RTEST(rb_funcall(rb_mFileTest, id_directory_p, 1, path)))
            return rb_funcall(rb_cDir, id_empty_p, 1, path);
        else
            return rb_funcall(rb_mFileTest, id_empty_p, 1, path);
    }

entries() click to toggle source

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

The results contains just the names in the directory, without any trailing slashes or recursive look-up.

    pp Pathname.new('/usr/local').entries
    #=> [#<Pathname:share>,
    #    #<Pathname:lib>,
    #    #<Pathname:..>,
    #    #<Pathname:include>,
    #    #<Pathname:etc>,
    #    #<Pathname:bin>,
    #    #<Pathname:man>,
    #    #<Pathname:games>,
    #    #<Pathname:.>,
    #    #<Pathname:sbin>,
    #    #<Pathname:src>]

The result may contain the current directory `#<Pathname:.>` and the parent directory `#<Pathname:..>`.

If you don’t want `.` and `..` and want directories, consider `Pathname#children`.

    static VALUE
    path_entries(VALUE self)
    {
        VALUE klass, str, ary;
        long i;
        klass = rb_obj_class(self);
        str = get_strpath(self);
        ary = rb_funcall(rb_cDir, id_entries, 1, str);
        ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            VALUE elt = RARRAY_AREF(ary, i);
            elt = rb_class_new_instance(1, &elt, klass);
            rb_ary_store(ary, i, elt);
        }
        return ary;
    }

eql?(p1)

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.

Alias for: ==
executable?() click to toggle source

See `FileTest.executable?`.

    static VALUE
    path_executable_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_executable_p, 1, get_strpath(self));
    }

executable_real?() click to toggle source

See `FileTest.executable_real?`.

    static VALUE
    path_executable_real_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_executable_real_p, 1, get_strpath(self));
    }

exist?() click to toggle source

See `FileTest.exist?`.

    static VALUE
    path_exist_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_exist_p, 1, get_strpath(self));
    }

expand_path(p1 = v1) click to toggle source

Returns the absolute path for the file.

See `File.expand_path`.

    static VALUE
    path_expand_path(int argc, VALUE *argv, VALUE self)
    {
        VALUE str = get_strpath(self);
        VALUE dname;
        if (rb_scan_args(argc, argv, "01", &dname) == 0)
            str = rb_funcall(rb_cFile, id_expand_path, 1, str);
        else
            str = rb_funcall(rb_cFile, id_expand_path, 2, str, dname);
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

extname() click to toggle source

Returns the file’s extension.

See `File.extname`.

    static VALUE
    path_extname(VALUE self)
    {
        VALUE str = get_strpath(self);
        return rb_funcall(rb_cFile, id_extname, 1, str);
    }

file?() click to toggle source

See `FileTest.file?`.

    static VALUE
    path_file_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_file_p, 1, get_strpath(self));
    }

find(ignore_error: true) { |pathname| ... } click to toggle source

Iterates over the directory tree in a depth first manner, yielding a `Pathname` for each file under “this” directory.

Returns an `Enumerator` if no block is given.

Since it is implemented by the standard library module `Find`, `Find.prune` can be used to control the traversal.

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

See `Find.find`

    # File ext/pathname/lib/pathname.rb, line 565
    def find(ignore_error: true) # :yield: pathname
      return to_enum(__method__, ignore_error: ignore_error) unless block_given?
      require 'find'
      if @path == '.'
        Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
      else
        Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) }
      end
    end

fnmatch(pattern, [flags]) → true or false click to toggle source

Return `true` if the receiver matches the given pattern.

See `File.fnmatch`.

    static VALUE
    path_fnmatch(int argc, VALUE *argv, VALUE self)
    {
        VALUE str = get_strpath(self);
        VALUE pattern, flags;
        if (rb_scan_args(argc, argv, "11", &pattern, &flags) == 1)
            return rb_funcall(rb_cFile, id_fnmatch, 2, pattern, str);
        else
            return rb_funcall(rb_cFile, id_fnmatch, 3, pattern, str, flags);
    }

Also aliased as: fnmatch?
fnmatch?(p1, p2 = v2)

Return `true` if the receiver matches the given pattern.

See `File.fnmatch`.

Alias for: fnmatch
freeze → obj click to toggle source

Freezes this `Pathname`.

See `Object.freeze`.

    static VALUE
    path_freeze(VALUE self)
    {
        rb_call_super(0, 0);
        rb_str_freeze(get_strpath(self));
        return self;
    }

ftype → string click to toggle source

Returns “type” of file (“file”, “directory”, etc).

See `File.ftype`.

    static VALUE
    path_ftype(VALUE self)
    {
        return rb_funcall(rb_cFile, id_ftype, 1, get_strpath(self));
    }

glob(p1, p2 = v2) click to toggle source

Returns or yields `Pathname` objects.

    Pathname("ruby-2.4.2").glob("R*.md")
    #=> [#<Pathname:ruby-2.4.2/README.md>, #<Pathname:ruby-2.4.2/README.ja.md>]

See `Dir.glob`. This method uses the `base` keyword argument of `Dir.glob`.

    static VALUE
    path_glob(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[3];
        int n;

        n = rb_scan_args(argc, argv, "11", &args[0], &args[1]);
        if (n == 1)
          args[1] = INT2FIX(0);

        args[2] = rb_hash_new();
        rb_hash_aset(args[2], ID2SYM(id_base), get_strpath(self));

        n = 3;

        if (rb_block_given_p()) {
            return rb_block_call_kw(rb_cDir, id_glob, n, args, glob_i, self, RB_PASS_KEYWORDS);
        }
        else {
            VALUE ary;
            long i;
            ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_KEYWORDS);
            ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
            for (i = 0; i < RARRAY_LEN(ary); i++) {
                VALUE elt = RARRAY_AREF(ary, i);
                elt = rb_funcall(self, '+', 1, elt);
                rb_ary_store(ary, i, elt);
            }
            return ary;
        }
    }

grpowned?() click to toggle source

See `FileTest.grpowned?`.

    static VALUE
    path_grpowned_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_grpowned_p, 1, get_strpath(self));
    }

join(*args) click to toggle source

Joins the given pathnames onto `self` to create a new `Pathname` object.

    path0 = Pathname.new("/usr")                # Pathname:/usr
    path0 = path0.join("bin/ruby")              # Pathname:/usr/bin/ruby
        # is the same as
    path1 = Pathname.new("/usr") + "bin/ruby"   # Pathname:/usr/bin/ruby
    path0 == path1
        #=> true

    # File ext/pathname/lib/pathname.rb, line 410
    def join(*args)
      return self if args.empty?
      result = args.pop
      result = Pathname.new(result) unless Pathname === result
      return result if result.absolute?
      args.reverse_each {|arg|
        arg = Pathname.new(arg) unless Pathname === arg
        result = arg + result
        return result if result.absolute?
      }
      self + result
    end

lchmod(mode_int) → integer click to toggle source

Same as `Pathname.chmod`, but does not follow symbolic links.

See `File.lchmod`.

    static VALUE
    path_lchmod(VALUE self, VALUE mode)
    {
        return rb_funcall(rb_cFile, id_lchmod, 2, mode, get_strpath(self));
    }

lchown(owner_int, group_int) → integer click to toggle source

Same as `Pathname.chown`, but does not follow symbolic links.

See `File.lchown`.

    static VALUE
    path_lchown(VALUE self, VALUE owner, VALUE group)
    {
        return rb_funcall(rb_cFile, id_lchown, 3, owner, group, get_strpath(self));
    }

lstat() click to toggle source

See `File.lstat`.

    static VALUE
    path_lstat(VALUE self)
    {
        return rb_funcall(rb_cFile, id_lstat, 1, get_strpath(self));
    }

make_link(old) click to toggle source

Creates a hard link at pathname.

See `File.link`.

    static VALUE
    path_make_link(VALUE self, VALUE old)
    {
        return rb_funcall(rb_cFile, id_link, 2, old, get_strpath(self));
    }

make_symlink(old) click to toggle source

Creates a symbolic link.

See `File.symlink`.

    static VALUE
    path_make_symlink(VALUE self, VALUE old)
    {
        return rb_funcall(rb_cFile, id_symlink, 2, old, get_strpath(self));
    }

mkdir(p1 = v1) click to toggle source

Create the referenced directory.

See `Dir.mkdir`.

    static VALUE
    path_mkdir(int argc, VALUE *argv, VALUE self)
    {
        VALUE str = get_strpath(self);
        VALUE vmode;
        if (rb_scan_args(argc, argv, "01", &vmode) == 0)
            return rb_funcall(rb_cDir, id_mkdir, 1, str);
        else
            return rb_funcall(rb_cDir, id_mkdir, 2, str, vmode);
    }

mkpath(mode: nil) click to toggle source

Creates a full path, including any intermediate directories that don’t yet exist.

See `FileUtils.mkpath` and `FileUtils.mkdir_p`

    # File ext/pathname/lib/pathname.rb, line 584
    def mkpath(mode: nil)
      FileUtils.mkpath(@path, mode: mode)
      nil
    end

mountpoint?() click to toggle source

Returns `true` if `self` points to a mountpoint.

    # File ext/pathname/lib/pathname.rb, line 199
    def mountpoint?
      begin
        stat1 = self.lstat
        stat2 = self.parent.lstat
        stat1.dev != stat2.dev || stat1.ino == stat2.ino
      rescue Errno::ENOENT
        false
      end
    end

mtime → time click to toggle source

Returns the last modified time of the file.

See `File.mtime`.

    static VALUE
    path_mtime(VALUE self)
    {
        return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
    }

open() click to toggle source
open(mode="r" [, opt]) → file
open([mode [, perm]] [, opt]) → file
open(mode="r" [, opt]) {|file| block } → obj
open([mode [, perm]] [, opt]) {|file| block } → obj

Opens the file for reading or writing.

See `File.open`.

    static VALUE
    path_open(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[4];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
        if (rb_block_given_p()) {
            return rb_block_call_kw(rb_cFile, id_open, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
        }
        else {
            return rb_funcallv_kw(rb_cFile, id_open, 1+n, args, RB_PASS_CALLED_KEYWORDS);
        }
    }

opendir() click to toggle source

Opens the referenced directory.

See `Dir.open`.

    static VALUE
    path_opendir(VALUE self)
    {
        VALUE args[1];

        args[0] = get_strpath(self);
        return rb_block_call(rb_cDir, id_open, 1, args, 0, 0);
    }

owned?() click to toggle source

See `FileTest.owned?`.

    static VALUE
    path_owned_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_owned_p, 1, get_strpath(self));
    }

parent() click to toggle source

Returns the parent directory.

This is same as `self + '..'`.

    # File ext/pathname/lib/pathname.rb, line 194
    def parent
      self + '..'
    end

pipe?() click to toggle source

See `FileTest.pipe?`.

    static VALUE
    path_pipe_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_pipe_p, 1, get_strpath(self));
    }

read([length [, offset]]) → string click to toggle source
read([length [, offset]], open_args) → string

Returns all data from the file, or the first `N` bytes if specified.

See `File.read`.

    static VALUE
    path_read(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[4];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
        return rb_funcallv_kw(rb_cFile, id_read, 1+n, args, RB_PASS_CALLED_KEYWORDS);
    }

readable?() click to toggle source

See `FileTest.readable?`.

    static VALUE
    path_readable_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_readable_p, 1, get_strpath(self));
    }

readable_real?() click to toggle source

See `FileTest.readable_real?`.

    static VALUE
    path_readable_real_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_readable_real_p, 1, get_strpath(self));
    }

readlines(sep=$/ [, open_args]) → array click to toggle source
readlines(limit [, open_args]) → array
readlines(sep, limit [, open_args]) → array

Returns all the lines from the file.

See `File.readlines`.

    static VALUE
    path_readlines(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[4];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
        return rb_funcallv_kw(rb_cFile, id_readlines, 1+n, args, RB_PASS_CALLED_KEYWORDS);
    }

readlink() click to toggle source

Read symbolic link.

See `File.readlink`.

    static VALUE
    path_readlink(VALUE self)
    {
        VALUE str;
        str = rb_funcall(rb_cFile, id_readlink, 1, get_strpath(self));
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

realdirpath(p1 = v1) click to toggle source

Returns the real (absolute) pathname of `self` in the actual filesystem.

Does not contain symlinks or useless dots, `..` and `.`.

The last component of the real pathname can be nonexistent.

    static VALUE
    path_realdirpath(int argc, VALUE *argv, VALUE self)
    {
        VALUE basedir, str;
        rb_scan_args(argc, argv, "01", &basedir);
        str = rb_funcall(rb_cFile, id_realdirpath, 2, get_strpath(self), basedir);
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

realpath(p1 = v1) click to toggle source

Returns the real (absolute) pathname for `self` in the actual filesystem.

Does not contain symlinks or useless dots, `..` and `.`.

All components of the pathname must exist when this method is called.

    static VALUE
    path_realpath(int argc, VALUE *argv, VALUE self)
    {
        VALUE basedir, str;
        rb_scan_args(argc, argv, "01", &basedir);
        str = rb_funcall(rb_cFile, id_realpath, 2, get_strpath(self), basedir);
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

relative?() click to toggle source

The opposite of `Pathname#absolute?`

It returns `false` if the pathname begins with a slash.

    p = Pathname.new('/im/sure')
    p.relative?
        #=> false

    p = Pathname.new('not/so/sure')
    p.relative?
        #=> true

    # File ext/pathname/lib/pathname.rb, line 246
    def relative?
      !absolute?
    end

relative_path_from(base_directory) click to toggle source

Returns a relative path from the given `base_directory` to the receiver.

If `self` is absolute, then `base_directory` must be absolute too.

If `self` is relative, then `base_directory` must be relative too.

This method doesn’t access the filesystem. It assumes no symlinks.

`ArgumentError` is raised when it cannot find a relative path.

Note that this method does not handle situations where the case sensitivity of the filesystem in use differs from the operating system default.

    # File ext/pathname/lib/pathname.rb, line 511
    def relative_path_from(base_directory)
      base_directory = Pathname.new(base_directory) unless base_directory.is_a? Pathname
      dest_directory = self.cleanpath.to_s
      base_directory = base_directory.cleanpath.to_s
      dest_prefix = dest_directory
      dest_names = []
      while r = chop_basename(dest_prefix)
        dest_prefix, basename = r
        dest_names.unshift basename if basename != '.'
      end
      base_prefix = base_directory
      base_names = []
      while r = chop_basename(base_prefix)
        base_prefix, basename = r
        base_names.unshift basename if basename != '.'
      end
      unless SAME_PATHS[dest_prefix, base_prefix]
        raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
      end
      while !dest_names.empty? &&
            !base_names.empty? &&
            SAME_PATHS[dest_names.first, base_names.first]
        dest_names.shift
        base_names.shift
      end
      if base_names.include? '..'
        raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
      end
      base_names.fill('..')
      relpath_names = base_names + dest_names
      if relpath_names.empty?
        Pathname.new('.')
      else
        Pathname.new(File.join(*relpath_names))
      end
    end

rename(p1) click to toggle source

Rename the file.

See `File.rename`.

    static VALUE
    path_rename(VALUE self, VALUE to)
    {
        return rb_funcall(rb_cFile, id_rename, 2, get_strpath(self), to);
    }

rmdir() click to toggle source

Remove the referenced directory.

See `Dir.rmdir`.

    static VALUE
    path_rmdir(VALUE self)
    {
        return rb_funcall(rb_cDir, id_rmdir, 1, get_strpath(self));
    }

rmtree() click to toggle source

Recursively deletes a directory, including all directories beneath it.

See `FileUtils.rm_r`

    # File ext/pathname/lib/pathname.rb, line 592
    def rmtree
      # The name "rmtree" is borrowed from File::Path of Perl.
      # File::Path provides "mkpath" and "rmtree".
      FileUtils.rm_r(@path)
      nil
    end

root?() click to toggle source

Predicate method for root directories. Returns `true` if the pathname consists of consecutive slashes.

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

    # File ext/pathname/lib/pathname.rb, line 216
    def root?
      chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o.match?(@path)
    end

setgid?() click to toggle source

See `FileTest.setgid?`.

    static VALUE
    path_setgid_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_setgid_p, 1, get_strpath(self));
    }

setuid?() click to toggle source

See `FileTest.setuid?`.

    static VALUE
    path_setuid_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_setuid_p, 1, get_strpath(self));
    }

size() click to toggle source

See `FileTest.size`.

    static VALUE
    path_size(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_size, 1, get_strpath(self));
    }

size?() click to toggle source

See `FileTest.size?`.

    static VALUE
    path_size_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_size_p, 1, get_strpath(self));
    }

socket?() click to toggle source

See `FileTest.socket?`.

    static VALUE
    path_socket_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_socket_p, 1, get_strpath(self));
    }

split() click to toggle source

Returns the `dirname` and the `basename` in an `Array`.

See `File.split`.

    static VALUE
    path_split(VALUE self)
    {
        VALUE str = get_strpath(self);
        VALUE ary, dirname, basename;
        ary = rb_funcall(rb_cFile, id_split, 1, str);
        Check_Type(ary, T_ARRAY);
        dirname = rb_ary_entry(ary, 0);
        basename = rb_ary_entry(ary, 1);
        dirname = rb_class_new_instance(1, &dirname, rb_obj_class(self));
        basename = rb_class_new_instance(1, &basename, rb_obj_class(self));
        return rb_ary_new3(2, dirname, basename);
    }

stat() click to toggle source

Returns a `File::Stat` object.

See `File.stat`.

    static VALUE
    path_stat(VALUE self)
    {
        return rb_funcall(rb_cFile, id_stat, 1, get_strpath(self));
    }

sticky?() click to toggle source

See `FileTest.sticky?`.

    static VALUE
    path_sticky_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_sticky_p, 1, get_strpath(self));
    }

sub(*args) click to toggle source

Return a pathname which is substituted by `String#sub`.

    path1 = Pathname.new('/usr/bin/perl')
    path1.sub('perl', 'ruby')
        #=> #<Pathname:/usr/bin/ruby>

    static VALUE
    path_sub(int argc, VALUE *argv, VALUE self)
    {
        VALUE str = get_strpath(self);

        if (rb_block_given_p()) {
            str = rb_block_call(str, id_sub, argc, argv, 0, 0);
        }
        else {
            str = rb_funcallv(str, id_sub, argc, argv);
        }
        return rb_class_new_instance(1, &str, rb_obj_class(self));
    }

sub_ext(p1) click to toggle source

Return a pathname with `repl` added as a suffix to the basename.

If self has no extension part, `repl` is appended.

    Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
        #=> #<Pathname:/usr/bin/shutdown.rb>

    static VALUE
    path_sub_ext(VALUE self, VALUE repl)
    {
        VALUE str = get_strpath(self);
        VALUE str2;
        long extlen;
        const char *ext;
        const char *p;

        StringValue(repl);
        p = RSTRING_PTR(str);
        extlen = RSTRING_LEN(str);
        ext = ruby_enc_find_extname(p, &extlen, rb_enc_get(str));
        if (ext == NULL) {
            ext = p + RSTRING_LEN(str);
        }
        else if (extlen <= 1) {
            ext += extlen;
        }
        str2 = rb_str_subseq(str, 0, ext-p);
        rb_str_append(str2, repl);
        return rb_class_new_instance(1, &str2, rb_obj_class(self));
    }

symlink?() click to toggle source

See `FileTest.symlink?`.

    static VALUE
    path_symlink_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_symlink_p, 1, get_strpath(self));
    }

sysopen([mode, [perm]]) → fixnum click to toggle source

See `IO.sysopen`.

    static VALUE
    path_sysopen(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[3];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
        return rb_funcallv(rb_cIO, id_sysopen, 1+n, args);
    }

taint → obj click to toggle source

Returns pathname. This method is deprecated and will be removed in Ruby 3.2.

    static VALUE
    path_taint(VALUE self)
    {
        rb_warn("Pathname#taint is deprecated and will be removed in Ruby 3.2.");
        return self;
    }

to_path → string

Return the path as a `String`.

`to_path` is implemented so `Pathname` objects are usable with `File.open`, etc.

Alias for: to_s
to_s → string click to toggle source

Return the path as a `String`.

`to_path` is implemented so `Pathname` objects are usable with `File.open`, etc.

    static VALUE
    path_to_s(VALUE self)
    {
        return rb_obj_dup(get_strpath(self));
    }

Also aliased as: to_path
truncate(p1) click to toggle source

Truncates the file to `length` bytes.

See `File.truncate`.

    static VALUE
    path_truncate(VALUE self, VALUE length)
    {
        return rb_funcall(rb_cFile, id_truncate, 2, get_strpath(self), length);
    }

unlink() click to toggle source

Removes a file or directory, using `File.unlink` if `self` is a file, or `Dir.unlink` as necessary.

    static VALUE
    path_unlink(VALUE self)
    {
        VALUE eENOTDIR = rb_const_get_at(rb_mErrno, id_ENOTDIR);
        VALUE str = get_strpath(self);
        return rb_rescue2(unlink_body, str, unlink_rescue, str, eENOTDIR, (VALUE)0);
    }

Also aliased as: delete
untaint → obj click to toggle source

Returns pathname. This method is deprecated and will be removed in Ruby 3.2.

    static VALUE
    path_untaint(VALUE self)
    {
        rb_warn("Pathname#untaint is deprecated and will be removed in Ruby 3.2.");
        return self;
    }

utime(p1, p2) click to toggle source

Update the access and modification times of the file.

See `File.utime`.

    static VALUE
    path_utime(VALUE self, VALUE atime, VALUE mtime)
    {
        return rb_funcall(rb_cFile, id_utime, 3, atime, mtime, get_strpath(self));
    }

world_readable?() click to toggle source

See `FileTest.world_readable?`.

    static VALUE
    path_world_readable_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_world_readable_p, 1, get_strpath(self));
    }

world_writable?() click to toggle source

See `FileTest.world_writable?`.

    static VALUE
    path_world_writable_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_world_writable_p, 1, get_strpath(self));
    }

writable?() click to toggle source

See `FileTest.writable?`.

    static VALUE
    path_writable_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_writable_p, 1, get_strpath(self));
    }

writable_real?() click to toggle source

See `FileTest.writable_real?`.

    static VALUE
    path_writable_real_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_writable_real_p, 1, get_strpath(self));
    }

write(string, [offset] ) → fixnum click to toggle source
write(string, [offset], open_args ) → fixnum

Writes `contents` to the file.

See `File.write`.

    static VALUE
    path_write(int argc, VALUE *argv, VALUE self)
    {
        VALUE args[4];
        int n;

        args[0] = get_strpath(self);
        n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
        return rb_funcallv_kw(rb_cFile, id_write, 1+n, args, RB_PASS_CALLED_KEYWORDS);
    }

zero?() click to toggle source

See `FileTest.zero?`.

    static VALUE
    path_zero_p(VALUE self)
    {
        return rb_funcall(rb_mFileTest, id_zero_p, 1, get_strpath(self));
    }