类 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)将包含更多信息。在某些情况下,会有一个简短的描述。

常量

版本

公共类方法

getwd() 点击以切换源

将当前工作目录作为 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) 点击以切换源

返回或产生 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;
    }
}
mktmpdir() { |dir| ... } 点击以切换源

创建一个临时目录,并将返回的路径包装在 Pathname 对象中。

请参阅 Dir.mktmpdir

# File pathname/lib/pathname.rb, line 610
def self.mktmpdir
  require 'tmpdir' unless defined?(Dir.mktmpdir)
  if block_given?
    Dir.mktmpdir do |dir|
      dir = self.new(dir)
      yield dir
    end
  else
    self.new(Dir.mktmpdir)
  end
end
new(p1) 点击以切换源

从给定的字符串(或类字符串对象)创建一个 Pathname 对象。如果 path 包含 NULL 字符 (\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>

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

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>

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

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".

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

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

测试文件是否为空。

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

返回目录中的条目(文件和子目录),每个条目都是一个 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?() 点击切换源码

请参阅 FileTest.executable?。

static VALUE
path_executable_p(VALUE self)
{
    return rb_funcall(rb_mFileTest, id_executable_p, 1, get_strpath(self));
}
executable_real?() 点击切换源码

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

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

返回文件的绝对路径。

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

返回文件的扩展名。

请参阅 File.extname。

static VALUE
path_extname(VALUE self)
{
    VALUE str = get_strpath(self);
    return rb_funcall(rb_cFile, id_extname, 1, str);
}
file?() 点击切换源码

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

以深度优先的方式迭代目录树,为“此”目录下的每个文件生成一个 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.delete_prefix('./')) }
  else
    Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) }
  end
end
fnmatch(pattern, [flags]) → true or 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 588
def mkpath(mode: nil)
  require 'fileutils'
  FileUtils.mkpath(@path, mode: mode)
  self
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 597
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)
  self
end
root?() 点击以切换源

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

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

# 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));
}