类 Pathname

Pathname 代表文件系统中文件或目录的名称,但不代表文件本身。

路径名取决于操作系统:Unix、Windows 等。此库适用于本地操作系统的路径名,但实验性地支持非 Unix 路径名。

Pathname 可以是相对路径或绝对路径。只有当你尝试引用文件时,它才会真正关心文件是否存在。

Pathname 是不可变的。它没有用于破坏性更新的方法。

本类的目标是以比标准 Ruby 更简洁的方式操作文件路径信息。以下示例演示了区别。

所有来自 File、FileTest 的功能,以及来自 Dir 和 FileUtils 的部分功能都包含在内,以一种不令人意外的方式。它本质上是所有这些功能的 фасадом,甚至更多。

示例

示例 1:使用 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| _ }

示例 2:使用标准 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| _ }

示例 3:特殊功能

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, ...]

功能分解

核心方法

这些方法实际上是在操作一个字符串,因为路径本身就是一个字符串。除了 mountpoint?childreneach_childrealdirpathrealpath 之外,这些方法都不会访问文件系统。

文件状态谓词方法

这些方法是 FileTest 的 фасадом

文件属性和操作方法

这些方法是 File 的 фасадом

目录方法

这些方法是 Dir 的一个外观

IO

这些方法是 IO 的一个外观

实用程序

这些方法是 Find、FileUtils 和其他方法的混合

方法文档

如上节所示,Pathname 中的大多数方法都是外观。这些方法的文档通常只说,“参见 FileTest.writable?”,因为您应该熟悉原始方法,并且它的文档(例如通过 ri)将包含更多信息。在某些情况下,会附带简短的描述。

常量

VERSION

公共类方法

getwd() click to toggle source

返回当前工作目录作为 Pathname

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

参见 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

返回或生成 Pathname 对象。

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

参见 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

从给定的字符串(或类似字符串的对象)创建一个 Pathname 对象。如果 path 包含空字符 (\0),则会引发 ArgumentError。

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() 点击切换源代码

返回当前工作目录作为 Pathname

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

参见 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);
}

公共实例方法

+(other) 点击切换源代码

将路径片段附加到 self 以生成一个新的 Pathname 对象。由于 other 被视为相对于 self 的路径,如果 other 是绝对路径,则新的 Pathname 对象将仅从 other 创建。

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

此方法不访问文件系统;它纯粹是字符串操作。

# File pathname/lib/pathname.rb, line 356
def +(other)
  other = Pathname.new(other) unless Pathname === other
  Pathname.new(plus(@path, other.to_s))
end
也称为:/
/(other)
别名:+
<=>(p1) 点击切换源代码

提供路径名的区分大小写的比较运算符。

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

它将根据左参数相对于右参数的值返回 -101。或者,如果参数不可比较,它将返回 nil

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) 点击切换源代码

将此路径名与 other 进行比较。比较是基于字符串的。请注意,两个不同的路径 (foo.txt./foo.txt) 可以引用同一个文件。

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));
}
也称为:===eql?
===(p1)

将此路径名与 other 进行比较。比较是基于字符串的。请注意,两个不同的路径 (foo.txt./foo.txt) 可以引用同一个文件。

别名:==
absolute?() 点击切换源代码

用于测试路径是否为绝对路径的谓词方法。

如果路径名以斜杠开头,则返回 true

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

p = Pathname.new('not/so/sure')
p.absolute?
    #=> false
# File pathname/lib/pathname.rb, line 233
def absolute?
  ABSOLUTE_PATH.match? @path
end
ascend() { |self| ... } 点击切换源代码

以升序迭代并为给定路径中的每个元素生成一个新的 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>
   #<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>

如果没有给出块,则返回一个枚举器。

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

它不访问文件系统。

# File pathname/lib/pathname.rb, line 330
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 点击切换源代码

返回文件的最后访问时间。

参见 File.atime。

static VALUE
path_atime(VALUE self)
{
    return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
}
basename(p1 = v1) 点击切换源代码

返回路径的最后一个组件。

参见 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 点击切换源代码

返回文件中的所有字节,如果指定,则返回前 N 个字节。

参见 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 点击切换源代码
binwrite(string, [offset], open_args ) → fixnum

contents 写入文件,以二进制模式打开。

参见 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 点击切换源代码

返回文件的创建时间。如果平台没有创建时间,则会引发 NotImplementedError。

参见 File.birthtime。

static VALUE
path_birthtime(VALUE self)
{
    return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
}
blockdev?() 点击切换源代码

参见 FileTest.blockdev?。

static VALUE
path_blockdev_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_blockdev_p, 1, get_strpath(self));
}
chardev?() 点击切换源代码

参见 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) 点击切换源代码

返回目录的子项(文件和子目录,非递归)作为 Pathname 对象的数组。

默认情况下,返回的路径名将包含访问文件所需的信息。如果将 with_directory 设置为 false,则返回的路径名将仅包含文件名。

例如

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, ... ]

请注意,结果中永远不会包含目录中的 ... 条目,因为它们不是子项。

# File pathname/lib/pathname.rb, line 449
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 点击切换源代码

更改文件权限。

参见 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 点击切换源代码

更改文件的拥有者和组。

参见 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) 点击切换源代码

返回 self 的干净路径名,其中连续的斜杠和无用的点已被移除。不会访问文件系统。

如果 consider_symlinktrue,则使用更保守的算法来避免破坏符号链接。这可能会保留比绝对必要更多的 .. 条目,但如果不访问文件系统,这是无法避免的。

参见 Pathname#realpath

# File pathname/lib/pathname.rb, line 94
def cleanpath(consider_symlink=false)
  if consider_symlink
    cleanpath_conservative
  else
    cleanpath_aggressive
  end
end
ctime → time 点击切换源代码

返回最后修改时间,使用目录信息,而不是文件本身。

参见 File.ctime。

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

删除文件或目录,如果 self 是文件,则使用 File.unlink,否则使用 Dir.unlink。

别名:unlink
descend() { |v| ... } 点击切换源代码

以降序遍历给定路径中的每个元素,并为每个元素生成一个新的 Pathname 对象。

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>

如果没有给出块,则返回一个枚举器。

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

它不访问文件系统。

# File pathname/lib/pathname.rb, line 297
def descend
  return to_enum(__method__) unless block_given?
  vs = []
  ascend {|v| vs << v }
  vs.reverse_each {|v| yield v }
  nil
end
directory?() 点击切换源代码

参见 FileTest.directory?。

static VALUE
path_directory_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_directory_p, 1, get_strpath(self));
}
dirname() 点击切换源代码

返回路径中除最后一个组件之外的所有组件。

参见 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) 点击切换源代码

遍历目录中的子项(文件和子目录,非递归)。

它为每个子项生成一个 Pathname 对象。

默认情况下,生成的路径名将包含访问文件所需的信息。

如果将 with_directory 设置为 false,则返回的路径名将只包含文件名。

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>

请注意,结果中永远不会包含目录中的 ... 条目,因为它们不是子项。

参见 Pathname#children

# File pathname/lib/pathname.rb, line 499
def each_child(with_directory=true, &b)
  children(with_directory).each(&b)
end
each_entry() 点击切换源代码

遍历目录中的条目(文件和子目录),为每个条目生成一个 Pathname 对象。

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

    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| ... } 点击切换源代码

遍历路径的每个组件。

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

如果没有给出块,则返回一个枚举器。

enum = Pathname.new("/usr/bin/ruby").each_filename
  # ... do stuff ...
enum.each { |e| ... }
  # yields "usr", "bin", and "ruby".
# File pathname/lib/pathname.rb, line 265
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| ... } 点击切换源代码
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

迭代文件中的每一行,并为每一行生成一个 String 对象。

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

测试文件是否为空。

参见 Dir#empty? 和 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

返回目录中的条目(文件和子目录),每个条目都是一个 Pathname 对象。

结果只包含目录中的名称,不包含任何尾部斜杠或递归查找。

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>]

结果可能包含当前目录 #<Pathname:.> 和父目录 #<Pathname:..>

如果您不想要 ... 并且想要目录,请考虑使用 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)

将此路径名与 other 进行比较。比较是基于字符串的。请注意,两个不同的路径 (foo.txt./foo.txt) 可以引用同一个文件。

别名:==
executable?() click to toggle source

参见 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

参见 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

参见 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

返回文件的绝对路径。

参见 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

返回文件的扩展名。

参见 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

参见 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

以深度优先的方式迭代目录树,为“此”目录下的每个文件生成一个 Pathname

如果没有给出块,则返回一个 Enumerator。

由于它是通过标准库模块 Find 实现的,因此可以使用 Find.prune 来控制遍历。

如果 self.,则生成的路径名以当前目录中的文件名开头,而不是 ./

参见 Find.find

# File pathname/lib/pathname.rb, line 571
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 或 false 点击切换源代码

如果接收者与给定模式匹配,则返回 true

参见 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);
}
也称为:fnmatch?
fnmatch?(p1, p2 = v2)

如果接收者与给定模式匹配,则返回 true

参见 File.fnmatch。

别名:fnmatch
freeze → obj 点击切换源代码

冻结此 Pathname

参见 Object.freeze。

static VALUE
path_freeze(VALUE self)
{
    rb_call_super(0, 0);
    rb_str_freeze(get_strpath(self));
    return self;
}
ftype → string 点击切换源代码

返回文件的“类型”(“文件”,“目录”等)。

参见 File.ftype。

static VALUE
path_ftype(VALUE self)
{
    return rb_funcall(rb_cFile, id_ftype, 1, get_strpath(self));
}
glob(p1, p2 = v2) 点击切换源代码

返回或生成 Pathname 对象。

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

参见 Dir.glob。此方法使用 Dir.glob 的 base 关键字参数。

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?() 点击切换源代码

参见 FileTest.grpowned?。

static VALUE
path_grpowned_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_grpowned_p, 1, get_strpath(self));
}
join(*args) 点击切换源代码

将给定的路径名连接到 self 上以创建一个新的 Pathname 对象。这实际上与使用 Pathname#+ 按顺序追加 self 和所有参数相同。

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 pathname/lib/pathname.rb, line 416
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 点击切换源代码

Pathname.chmod 相同,但不跟踪符号链接。

参见 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 点击切换源代码

Pathname.chown 相同,但不跟踪符号链接。

参见 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() 点击切换源代码

参见 File.lstat。

static VALUE
path_lstat(VALUE self)
{
    return rb_funcall(rb_cFile, id_lstat, 1, get_strpath(self));
}
lutime(p1, p2) 点击切换源代码

更新文件的访问和修改时间。

Pathname#utime 相同,但不跟踪符号链接。

参见 File.lutime。

static VALUE
path_lutime(VALUE self, VALUE atime, VALUE mtime)
{
    return rb_funcall(rb_cFile, id_lutime, 3, atime, mtime, get_strpath(self));
}
mkdir(p1 = v1) 点击切换源代码

创建引用的目录。

参见 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) 点击切换源代码

创建完整路径,包括任何尚未存在的中间目录。

参见 FileUtils.mkpath 和 FileUtils.mkdir_p

# File pathname/lib/pathname.rb, line 590
def mkpath(mode: nil)
  FileUtils.mkpath(@path, mode: mode)
  nil
end
mountpoint?() 点击切换源代码

如果 self 指向挂载点,则返回 true

# File pathname/lib/pathname.rb, line 201
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 点击切换源代码

返回文件的最后修改时间。

参见 File.mtime。

static VALUE
path_mtime(VALUE self)
{
    return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
}
open() 点击切换源代码
open(mode="r" [, opt]) → file
open([mode [, perm]] [, opt]) → file
open(mode="r" [, opt]) {|file| block } → obj
open([mode [, perm]] [, opt]) {|file| block } → obj

打开文件以进行读写。

参见 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() 点击切换源代码

打开引用的目录。

参见 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?() 点击切换源代码

参见 FileTest.owned?。

static VALUE
path_owned_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_owned_p, 1, get_strpath(self));
}
parent() 点击切换源代码

返回父目录。

这与 self + '..' 相同。

# File pathname/lib/pathname.rb, line 196
def parent
  self + '..'
end
pipe?() 点击切换源代码

参见 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 点击切换源代码
read([length [, offset]], open_args) → string

返回文件中的所有数据,如果指定,则返回前 N 个字节。

参见 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?() 点击切换源代码

参见 FileTest.readable?。

static VALUE
path_readable_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_readable_p, 1, get_strpath(self));
}
readable_real?() 点击切换源代码

参见 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 点击切换源代码
readlines(limit [, open_args]) → array
readlines(sep, limit [, open_args]) → array

返回文件中的所有行。

参见 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);
}
realdirpath(p1 = v1) 点击切换源代码

返回 self 在实际文件系统中的真实(绝对)路径。

不包含符号链接或无用的点,...

真实路径的最后一个组件可能不存在。

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) 点击切换源代码

返回 self 在实际文件系统中的真实(绝对)路径。

不包含符号链接或无用的点,...

调用此方法时,路径的所有组件都必须存在。

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?() 点击切换源代码

Pathname#absolute? 相反。

如果路径以斜杠开头,则返回 false

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

p = Pathname.new('not/so/sure')
p.relative?
    #=> true
# File pathname/lib/pathname.rb, line 248
def relative?
  !absolute?
end
relative_path_from(base_directory) 点击切换源代码

返回从给定的 base_directory 到接收者的相对路径。

如果 self 是绝对路径,则 base_directory 也必须是绝对路径。

如果 self 是相对路径,则 base_directory 也必须是相对路径。

此方法不访问文件系统。它假设没有符号链接。

当找不到相对路径时,会引发 ArgumentError。

请注意,此方法不处理使用中的文件系统的大小写敏感性与操作系统默认值不同的情况。

# File pathname/lib/pathname.rb, line 517
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) 点击切换源代码

重命名文件。

参见 File.rename。

static VALUE
path_rename(VALUE self, VALUE to)
{
    return rb_funcall(rb_cFile, id_rename, 2, get_strpath(self), to);
}
rmdir() 点击切换源代码

删除引用的目录。

参见 Dir.rmdir。

static VALUE
path_rmdir(VALUE self)
{
    return rb_funcall(rb_cDir, id_rmdir, 1, get_strpath(self));
}
rmtree(noop: nil, verbose: nil, secure: nil) 点击切换源代码

递归删除目录,包括其下方的所有目录。

参见 FileUtils.rm_rf

# File pathname/lib/pathname.rb, line 598
def rmtree(noop: nil, verbose: nil, secure: nil)
  # The name "rmtree" is borrowed from File::Path of Perl.
  # File::Path provides "mkpath" and "rmtree".
  require 'fileutils'
  FileUtils.rm_rf(@path, noop: noop, verbose: verbose, secure: secure)
  nil
end
root?() 点击切换源代码

根目录的谓词方法。如果路径名由连续的斜杠组成,则返回 true

它不访问文件系统。因此,它可能对指向根目录的某些路径名返回 false,例如 /usr/..

# File pathname/lib/pathname.rb, line 218
def root?
  chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o.match?(@path)
end
setgid?() 点击切换源代码

参见 FileTest.setgid?。

static VALUE
path_setgid_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_setgid_p, 1, get_strpath(self));
}
setuid?() 点击切换源代码

参见 FileTest.setuid?。

static VALUE
path_setuid_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_setuid_p, 1, get_strpath(self));
}
size() 点击切换源代码

参见 FileTest.size。

static VALUE
path_size(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_size, 1, get_strpath(self));
}
size?() 点击切换源代码

参见 FileTest.size?。

static VALUE
path_size_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_size_p, 1, get_strpath(self));
}
socket?() 点击切换源代码

参见 FileTest.socket?。

static VALUE
path_socket_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_socket_p, 1, get_strpath(self));
}
split() 点击切换源代码

返回一个包含 dirnamebasename 的数组。

参见 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() 点击切换源代码

返回一个 File::Stat 对象。

参见 File.stat。

static VALUE
path_stat(VALUE self)
{
    return rb_funcall(rb_cFile, id_stat, 1, get_strpath(self));
}
sticky?() 点击切换源代码

参见 FileTest.sticky?。

static VALUE
path_sticky_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_sticky_p, 1, get_strpath(self));
}
sub(*args) 点击切换源代码

返回一个通过 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) 点击切换源代码

返回一个在基本名称后添加 repl 作为后缀的路径名。

如果 self 没有扩展部分,则附加 repl

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));
}
sysopen([mode, [perm]]) → fixnum 点击切换源代码

参见 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);
}
to_path → string

以字符串形式返回路径。

to_path 的实现使 Pathname 对象可用于 File.open 等。

别名:to_s
to_s → string 点击切换源代码

以字符串形式返回路径。

to_path 的实现使 Pathname 对象可用于 File.open 等。

static VALUE
path_to_s(VALUE self)
{
    return rb_obj_dup(get_strpath(self));
}
也称为:to_path
truncate(p1) 点击切换源代码

将文件截断为 length 字节。

参见 File.truncate。

static VALUE
path_truncate(VALUE self, VALUE length)
{
    return rb_funcall(rb_cFile, id_truncate, 2, get_strpath(self), length);
}
utime(p1, p2) 点击切换源代码

更新文件的访问和修改时间。

参见 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?() 点击切换源代码

参见 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?() 点击切换源代码

参见 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?() 点击切换源代码

参见 FileTest.writable?。

static VALUE
path_writable_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_writable_p, 1, get_strpath(self));
}
writable_real?() 点击切换源代码

参见 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 点击切换源代码
write(string, [offset], open_args ) → fixnum

contents 写入文件。

参见 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?() 点击切换源代码

参见 FileTest.zero?。

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