class IO::Path is Cool does IO { }

IO::Path 是 IO 操作的主力军。

从概念上讲,IO::Path 对象由卷、目录和基本名称组成。它支持纯文本操作和访问文件系统(例如,解析路径或读取文件的所有内容)的操作。

在创建时,每个 IO::Path 对象都会获得有关当前工作目录的信息,该路径可能相对于使用 $.CWD 属性(默认为 $*CWD)的路径,以及使用特殊 IO::Spec 类型在 $.SPEC 属性中给出的路径操作应使用什么操作系统语义。

$.SPEC 默认为 $*SPEC 的值,它使用适合代码当前运行的操作系统的对象。这是大多数代码都会感到满意的默认值。

在某些情况下(例如测试),您可能希望强制 $*SPEC 使用特定 SPEC 模块之一:IO::Spec::UnixIO::Spec::Win32IO::Spec::CygwinIO::Spec::QNX,或通过快捷方式子类 IO::Path::UnixIO::Path::Win32IO::Path::CygwinIO::Path::QNX 创建 IO::Path 对象,这些子类为您预设了 $.SPEC 属性。

除非另有说明,否则本文档的其余部分在其示例中默认采用 Unix 语义。

方法§

方法 new§

multi method new(Str:D $pathIO::Spec :$SPEC = $*SPECStr() :$CWD = $*CWD)
multi method new(
    :$basename!:$dirname = '.':$volume = ''
    IO::Spec :$SPEC = $*SPECStr() :$CWD = $*CWD
)

从路径字符串(正在解析卷、目录名和基本名)或从作为命名参数传递的卷、目录名和基本名创建一个新的 IO::Path 对象。

路径的操作将使用 :$SPEC 语义(默认为当前 $*SPEC)执行,并将使用 :$CWD 作为路径的相对目录(默认为 $*CWD)。

如果 $path 包含空字节,它将抛出一个异常,并显示一条消息:“不能将空字符 (U+0000) 用作路径的一部分”。

属性 CWD§

IO::Path.new("foo":CWD</home/camelia>)
    .CWD.say# OUTPUT: «/home/camelia␤»

只读。包含 .new:$CWD 参数的隐式或显式值。

属性 SPEC§

IO::Path.new("foo":SPEC(IO::Spec::Unix.new))\
    .SPEC.^name.say# OUTPUT: «IO::Spec::Unix␤»

只读。包含 .new:$SPEC 参数的隐式或显式值。

属性 path§

IO::Path.new("foo").path.say# OUTPUT: «foo␤»

只读。返回对象构造时的字符串,或者如果使用了 .new 的多部分版本,则返回 $SPEC.join($volume, $dirname, $basename) 的值。注意:这不包括 $.CWD;有关包括 $.CWD 的字符串化选项,请参见 IO::Path.absoluteIO::Path.relative

注意:实现可能会缓存使用此属性执行的操作,因此不建议修改其值(通过克隆或代理),否则可能会导致 IO::Path 对象损坏。相反,创建一个新的 IO::Path 对象。

方法 ACCEPTS§

multi method ACCEPTS(IO::Path:D: Cool:D $other --> Bool:D)

必要时将参数强制转换为 IO::Path。如果两个路径上的 .absolute 方法返回相同的字符串,则返回 True注意:如果两个路径的构造方式不同且从未完全解析,则表面上指向同一资源的两个路径可能不会 smartmatch 为 True

say "foo/../bar".IO ~~ "bar".IO # False

原因是上面两个路径在完全解析后可能指向不同的资源(例如,如果 foo 是一个符号链接)。在 smartmatch 之前解析路径以检查它们是否指向同一资源

say "foo/../bar".IO.resolve(:completely~~ "bar".IO.resolve(:completely# True

方法 basename§

method basename(IO::Path:D:)

返回路径对象的基名部分,它是路径引用的文件系统对象本身的名称。

"docs/README.pod".IO.basename.say# OUTPUT: «README.pod␤» 
"/tmp/".IO.basename.say;           # OUTPUT: «tmp␤»

请注意,在 IO::Spec::Win32 语义中,Windows 共享的 basename\,而不是共享本身的名称

IO::Path::Win32.new('//server/share').basename.say# OUTPUT: «\␤»

方法 add§

method add(IO::Path:D: Str() $what --> IO::Path:D)

将路径片段连接到调用者并返回生成的 IO::Path。如果将 ../ 添加到以文件结尾的路径,则可能需要调用 resolve,以便其他 IO::Path 方法(如 diropen)可以访问生成的路径。另请参阅 siblingparent

"foo/bar".IO.mkdir;
"foo/bar".IO.add("meow")    .resolve.relative.say# OUTPUT: «foo/bar/meow␤» 
"foo/bar".IO.add("/meow")   .resolve.relative.say# OUTPUT: «foo/bar/meow␤» 
"foo/bar".IO.add("meow.txt").resolve.relative.say# OUTPUT: «foo/bar/meow.txt␤» 
"foo/bar".IO.add("../meow".resolve.relative.say# OUTPUT: «foo/meow␤» 
"foo/bar".IO.add("../../")  .resolve.relative.say# OUTPUT: «.␤» 
 
method add(IO::Path:D: *@parts --> IO::Path:D)

从 Rakudo 编译器的 2021.07 版本开始,还可以指定要添加到路径的多个部分。

"foo".IO.add(<bar baz>).resolve.relative.say;      # OUTPUT: «foo/bar/baz␤»

方法 child§

method child(IO::Path:D: Str() $childname --> IO::Path:D)

.add 的别名。

方法 cleanup§

method cleanup(IO::Path:D: --> IO::Path:D)

返回一个新路径,它是调用者路径的规范表示形式,清理掉任何无关的路径部分

"foo/./././..////bar".IO.cleanup.say;      # OUTPUT: «"foo/../bar".IO␤» 
IO::Path::Win32.new("foo/./././..////bar")
    .cleanup.say"foo\..\bar".IO;         # OUTPUT: «"foo\..\bar".IO␤»

请注意,不会进行任何文件系统访问。另请参阅 resolve

方法 comb§

method comb(IO::Path:D: |args --> Seq:D)

打开文件并处理其内容的方式与 Str.comb 相同,采用相同的参数。在调用此方法时,实现可能会将文件全部吸入。

方法 split§

method split(IO::Path:D: |args --> Seq:D)

打开文件并处理其内容的方式与 Str.split 相同,采用相同参数。在调用此方法时,实现可能会将文件全部吸入。

方法 extension§

multi method extension(IO::Path:D:                                         --> Str:D)
multi method extension(IO::Path:D:               Int :$parts               --> Str:D)
multi method extension(IO::Path:D:             Range :$parts               --> Str:D)
multi method extension(IO::Path:D: Str $subst,   Int :$partsStr :$joiner --> IO::Path:D)
multi method extension(IO::Path:D: Str $substRange :$partsStr :$joiner --> IO::Path:D)

返回由 $parts 部分组成的扩展名(默认为 1),其中“部分”定义为一个点后跟可能为空的字符串,直到字符串末尾或前一部分。即 "foo.tar.gz" 有一个由两部分组成的扩展名:第一部分是 "gz",第二部分是 "tar",调用 "foo.tar.gz".IO.extension: :2parts 会得到 "tar.gz"。如果找不到具有指定数量 $parts 的扩展名,则返回一个空字符串。

$parts 可以是一个 Range,指定扩展名应具有的最小部分数和最大部分数。该例程将尝试匹配它能匹配的大多数部分。如果 $parts 范围的端点小于 0,则它们将被视为 0;实现可能会将大于 2⁶³-1 的端点视为 2⁶³-1。具有 NaNStr 端点的范围将导致抛出异常。

如果提供了 $subst,则扩展名将被替换为 $subst,并返回一个新的 IO::Path 对象。它将使用 $joiner 连接到文件名称,当 $subst 为空字符串时,默认为空字符串,当 $subst 不为空时,默认为 "."注意:如果替换的结果是路径的 basename 最终为空,则假定它为 .(一个点)。

# Getting an extension: 
say "foo.tar.gz".IO.extension;               # OUTPUT: «gz␤» 
say "foo.tar.gz".IO.extension: :2parts;      # OUTPUT: «tar.gz␤» 
say "foo.tar.gz".IO.extension: :parts(^5);   # OUTPUT: «tar.gz␤» 
say "foo.tar.gz".IO.extension: :parts(0..1); # OUTPUT: «gz␤» 
 
# Replacing an extension 
say "foo.tar.gz".IO.extension: '';                # OUTPUT: «"foo.tar".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP';             # OUTPUT: «"foo.tar.ZIP".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP':0parts;    # OUTPUT: «"foo.tar.gz.ZIP".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP':2parts;    # OUTPUT: «"foo.ZIP".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP':parts(^5); # OUTPUT: «"foo.ZIP".IO␤» 
 
# Replacing an extension using non-standard joiner: 
say "foo.tar.gz".IO.extension: '',    :joiner<_>;  # OUTPUT: «"foo.tar_".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP':joiner<_>;  # OUTPUT: «"foo.tar_ZIP".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP':joiner<_>,
                                       :2parts;     # OUTPUT: «"foo_ZIP".IO␤» 
say "foo.tar.gz".IO.extension: 'ZIP':joiner<_>,
                                       :parts(^5);  # OUTPUT: «"foo_ZIP".IO␤» 
 
# EDGE CASES: 
 
# There is no 5-part extension, so returned value is an empty string 
say "foo.tar.gz".IO.extension: :5parts; # OUTPUT: «␤» 
 
# There is no 5-part extension, so we replaced nothing: 
say "foo.tar.gz".IO.extension: 'ZIP':5parts; # OUTPUT: «"foo.tar.gz".IO␤» 
 
# Replacing a 0-part extension is just appending: 
say "foo.tar.gz".IO.extension: 'ZIP':0parts; # OUTPUT: «"foo.tar.gz.ZIP".IO␤» 
 
# Replace 1-part of the extension, using '.' joiner 
say "...".IO.extension: 'tar'# OUTPUT: «"...tar".IO␤» 
 
# Replace 1-part of the extension, using empty string joiner 
say "...".IO.extension: 'tar':joiner(''); # OUTPUT: «"..tar".IO␤» 
 
# Remove 1-part extension; results in empty basename, so result is ".".IO 
say ".".IO.extension: ''# OUTPUT: «".".IO␤»

方法 dirname§

method dirname(IO::Path:D:)

返回路径对象的目录名称部分。也就是说,它返回不包括 volumebase name 的路径。除非 dirname 由目录分隔符组成(即它是顶级目录),否则返回的值中不会 包含尾随目录分隔符。

say IO::Path.new("/home/camelia/myfile.raku").dirname# OUTPUT: «/home/camelia␤» 
say IO::Path::Win32.new("C:/home/camelia").dirname;  # OUTPUT: «/home␤» 
say IO::Path.new("/home").dirname;                   # OUTPUT: «/␤»

方法 volume§

method volume(IO::Path:D:)

返回路径对象的卷部分。在 Unix 系统上,这始终为空字符串。

say IO::Path::Win32.new("C:\\Windows\\registry.ini").volume;    # OUTPUT: «C:␤»

方法 parts§

method parts(IO::Path:D:)

为调用者返回一个 IO::Path::Parts

say IO::Path::Win32.new("C:/rakudo/raku.bat").parts.raku;
# OUTPUT: «IO::Path::Parts.new("C:","/rakudo","raku.bat")␤»

注意:在 Rakudo 版本 2020.06 之前,返回一个 Map,其键为 volumedirnamebasename,其值分别为调用者的各个部分。

方法 raku§

method raku(IO::Path:D: --> Str:D)

返回一个字符串,当通过 EVAL 传递时,会返回原始调用者。

"foo/bar".IO.raku.say;
# OUTPUT: IO::Path.new("foo/bar", :SPEC(IO::Spec::Unix), :CWD("/home/camelia")) 

请注意,此字符串包括 .CWD 属性的值,该属性在默认情况下在创建路径对象时设置为 $*CWD

方法 gist§

method gist(IO::Path:D: --> Str:D)

返回一个字符串,其中一部分包含 .absolute(如果路径是绝对路径)或 .path 的值。请注意,不会转义特殊字符,例如 "\b" 表示路径包含一个反斜杠和字母“b”,而不是退格符。

say "foo/bar".IO;                       # OUTPUT: «"foo/bar".IO␤» 
say IO::Path::Win32.new: C:\foo/bar\# OUTPUT: «"C:\foo/bar\".IO␤»

方法 Str§

method Str(IO::Path:D: --> Str)

IO::Path.path 的别名。特别地,请注意,IO::Path 的默认字符串化不会使用 $.CWD 属性 的值。要保留完整路径信息进行字符串化,请使用 .absolute.relative 方法。

方法 succ§

method succ(IO::Path:D: --> IO::Path:D)

返回一个新的 IO::Path,该 IO::Path 由调用者构建,其中 .basename 通过调用 Str.succ 进行更改。

"foo/file02.txt".IO.succ.say# OUTPUT: «"foo/file03.txt".IO␤»

方法 open§

method open(IO::Path:D: *%opts)

以文件形式打开路径;命名的选项控制模式,并且与 open 函数接受的选项相同。

方法 pred§

method pred(IO::Path:D: --> IO::Path:D)

返回一个新的 IO::Path,该 IO::Path 由调用者构建,其中 .basename 通过调用 Str.pred 进行更改。

"foo/file02.txt".IO.pred.say# OUTPUT: «"foo/file01.txt".IO␤»

方法 watch§

method watch(IO::Path:D: --> Supply:D)

等效于使用调用者作为参数调用 IO::Notification.watch-path

方法 is-absolute§

method is-absolute(IO::Path:D: --> Bool)

如果路径是绝对路径,则返回 True,否则返回 False

"/foo".IO.is-absolute.say# OUTPUT: «True␤» 
"bars".IO.is-absolute.say# OUTPUT: «False␤»

请注意,在 Windows 上,即使没有给出卷,以斜杠或反斜杠开头的路径仍被视为绝对路径,因为它对于该特定卷是绝对的。

IO::Path::Win32.new("/foo"  ).is-absolute.say# OUTPUT: «True␤» 
IO::Path::Win32.new("C:/foo").is-absolute.say# OUTPUT: «True␤» 
IO::Path::Win32.new("C:foo" ).is-absolute.say# OUTPUT: «False␤»

方法 is-relative§

method is-relative(IO::Path:D: --> Bool)

如果路径是相对路径,则返回 True,否则返回 False。适用于 .is-absolute 的 Windows 注意事项。

方法 absolute§

multi method absolute(IO::Path:D: --> Str)
multi method absolute(IO::Path:D: $base --> Str)

返回一个新的 Str 对象,该对象是一个绝对路径。如果调用者还不是一个绝对路径,则首先使用 $base 作为基础使其成为绝对路径(如果提供了 $base),或者使用创建对象时的 .CWD 属性(如果没有提供)。

方法 relative§

method relative(IO::Path:D: $base = $*CWD --> Str)

返回一个新的 Str 对象,其路径相对于 $base。如果未提供 $base,则使用 $*CWD 代替。如果调用者不是绝对路径,则首先使用创建对象时的 .CWD 属性使其成为绝对路径,然后使其相对于 $base

方法 parent§

multi method parent(IO::Path:D:)
multi method parent(IO::Path:D: UInt:D $level)

返回调用者的父路径。请注意,不会进行实际的文件系统访问,因此返回的父级是物理父级,而不是符号链接目录的逻辑父级。

'/etc/foo'.IO.parent.say# OUTPUT: «"/etc".IO␤» 
'/etc/..' .IO.parent.say# OUTPUT: «"/etc".IO␤» 
'/etc/../'.IO.parent.say# OUTPUT: «"/etc".IO␤» 
'./'      .IO.parent.say# OUTPUT: «"..".IO␤» 
'foo'     .IO.parent.say# OUTPUT: «".".IO␤» 
'/'       .IO.parent.say# OUTPUT: «"/".IO␤» 
IO::Path::Win32.new('C:/').parent.say# OUTPUT: «"C:/".IO␤»

如果指定了 $level,则该调用等效于调用 .parent() $level

say "/etc/foo".IO.parent(2eqv "/etc/foo".IO.parent.parent# OUTPUT: «True␤» 

方法 resolve§

method resolve(IO::Path:D: :$completely --> IO::Path)

返回一个新的 IO::Path 对象,其中所有符号链接和对父目录 (..) 的引用都已解析。这意味着将检查路径中每个目录的文件系统,并遵循找到的任何符号链接。

# bar is a symlink pointing to "/baz" 
my $io = "foo/./bar/..".IO.resolve;      # now "/" (the parent of "/baz")

如果将默认为 False:$completely 设置为真值,则如果该方法无法完全解析路径,该方法将使用 X::IO::Resolve fail,否则,它将尽可能多地解析,并且只会对路径的其余部分执行 cleanup。路径的最后一部分不必存在于 :$completely 中才能解析路径。

注意:目前(2017 年 4 月),此方法在所有平台上(例如 Windows)上都不能正常工作,因为 resolve 假设 POSIX 语义。

例程 dir§

multi  dir(*%_)
multi  dir(IO::Path:D $path|c)
multi  dir(IO()       $path|c)
method dir(IO::Path:D: Mu :$test = $*SPEC.curupdir)

返回一个惰性列表,其中包含与目录中的条目对应的 IO::Path 对象,这些条目可以按 :test 参数对它们的名称作为字符串进行 智能匹配 进行可选筛选。文件系统返回条目的顺序决定了列表中条目/对象顺序。不包括对应于特殊目录条目 ... 的对象。$path 确定对象的路径是绝对路径还是相对路径。

由于测试是针对 Str 参数执行的,而不是 IO,因此测试是在 $*CWD 中执行的,而不是在目标目录中。在针对文件测试运算符进行测试时,此方法将不起作用

dir('mydir'test => { .IO.d })

而这将起作用

dir('mydir'test => { "mydir/$_".IO.d })

注意:dir 调用会打开一个目录以供读取,这会算入程序的最大每个进程打开文件数。务必在执行类似于递归执行更多 dir 调用的操作之前耗尽返回的 Seq。你可以通过赋值给一个 @- 符号变量或简单地对其进行循环来耗尽它。请注意,以下示例将要进一步查看的目录推送到 Array 中,而不是立即对其调用 dir。另请参阅 IO::Dir 模块,它可以让你更精细地控制关闭目录句柄。

示例

# To iterate over the contents of the current directory: 
for dir() -> $file {
    say $file;
}
 
# As before, but include even '.' and '..' which are filtered out by 
# the default :test matcher: 
for dir(test => *-> $file {
    say $file;
}
 
# To get the names of all .jpg and .jpeg files in the home directory of the current user: 
my @jpegs = $*HOME.dir: test => /:i '.' jpe?$/;

一个列出所有文件和目录(递归)的示例程序

sub MAIN($dir = '.'{
    my @todo = $dir.IO;
    while @todo {
        for @todo.pop.dir -> $path {
            say $path.Str;
            @todo.push: $path if $path.d;
        }
    }
}

一种从当前目录开始递归查找以 ".raku" 结尾的前三个文件的惰性方式

my @stack = '.'.IO;
my $raku-files = gather while @stack {
    with @stack.pop {
        when :d { @stack.append: .dir }
        .take when .extension.lc eq 'raku'
    }
}
.put for $raku-files[^3];

文件测试运算符§

对于大多数文件测试,你可以执行智能匹配 ~~ 或调用一个方法。你不需要以传统方式实际打开一个文件句柄(尽管你可以这样做)来执行文件测试。你只需将 .IO 附加到文件名并将其智能匹配到一个测试副词。例如,以下是如何使用智能匹配检查文件是否可读

'/path/to/file'.IO ~~ :r;

文件测试包括

这些测试不会缓存早期测试执行的结果。

对 Pair 进行智能匹配 可用于一次执行多个测试

say :d & :x;                # OUTPUT: «all(d => True, x => True)␤» 
say '/tmp'.IO ~~ :d & :x;   # OUTPUT: «True␤» 
say '/'.IO    ~~ :d & :rw;  # OUTPUT: «False␤»

以上所有测试都可以用作方法(不带冒号),尽管方法测试可能会抛出 X::IO::DoesNotExist,如下所述。只有三个测试以方法形式存在:accessedchangedmodified

你还可以通过针对文件句柄的 .path 方法进行测试,对已打开的文件句柄执行文件测试。例如,给定文件句柄 $fh

$fh.path ~~ :r;
$fh.path.r;       # method form 

方法 e§

method e(IO::Path:D: --> Bool:D)

如果调用者是一个存在的路径,则返回 True

方法 d§

method d(IO::Path:D: --> Bool:D)

如果调用者是一个存在的路径且是一个目录,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 f§

method f(IO::Path:D: --> Bool:D)

如果调用者是一个存在的文件路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 s§

method s(IO::Path:D: --> Int:D)

返回文件大小(以字节为单位)。可以对目录路径进行调用,在这种情况下,报告的大小取决于操作系统。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

say $*EXECUTABLE.IO.s# OUTPUT: «467␤»

方法 l§

method l(IO::Path:D: --> Bool:D)

如果调用者是一个存在且是符号链接的路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 r§

method r(IO::Path:D: --> Bool:D)

如果调用者是一个存在且可访问的路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 w§

method w(IO::Path:D: --> Bool:D)

如果调用者是一个存在且可写的路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 rw§

method rw(IO::Path:D: --> Bool:D)

如果调用者是一个存在且可读写路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 x§

method x(IO::Path:D: --> Bool:D)

如果调用者是一个存在且可执行的路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

注意:如果文件是一个脚本(一个可执行文本文件,而不是一个本机可执行文件),并且该文件只有可执行权限而没有读取权限,则此方法将返回 True,但尝试执行将失败。这是操作系统的限制。

方法 rwx§

method rwx(IO::Path:D: --> Bool:D)

如果调用者是一个存在且可执行、可读写路径,则返回 True。如果路径指向一个不存在的文件系统实体,则该方法将使用 X::IO::DoesNotExist fail

方法 z§

method z(IO::Path:D: --> Bool:D)

如果调用者是一个存在且大小为 0 的路径,则返回 True。可以对目录路径调用该方法,在这种情况下,报告的文件大小(以及该方法的结果)取决于操作系统。如果路径指向一个不存在的文件系统实体,该方法将使用 X::IO::DoesNotExist fail

方法 sibling§

method sibling(IO::Path:D: Str() $sibling --> IO::Path:D)

允许引用同级文件或目录。返回一个基于调用者的新 IO::Path,其中 .basename 更改为 $sibling$sibling 可以是一个多部分路径片段;另请参见 .add

say '.bashrc'.IO.sibling: '.bash_aliases'# OUTPUT: «.bash_aliases".IO␤» 
say '/home/camelia/.bashrc'.IO.sibling: '.bash_aliases';
# OUTPUT: «/home/camelia/.bash_aliases".IO␤» 
 
say '/foo/' .IO.sibling: 'bar';  # OUTPUT: «/bar".IO␤» 
say '/foo/.'.IO.sibling: 'bar';  # OUTPUT: «/foo/bar".IO␤»

方法 words§

method words(IO::Path:D: :$chomp = True:$enc = 'utf8':$nl-in = ["\x0A""\r\n"], |c --> Seq:D)

打开调用者并返回其 words

该行为等同于 打开 调用者指定的文件,将 :$chomp:$enc:$nl-in 参数转发到 IO::Handle.open,然后在该句柄上调用 IO::Handle.words,将任何剩余参数转发到该方法,并返回结果 Seq

注意:单词是惰性读取的。在返回的 Seq 完全具体化 之前,底层使用的句柄不会关闭,这可能导致打开的文件句柄泄漏。可以使用 $limit 参数 避免打开的文件句柄泄漏,以减少要生成的单词 Seq

my %dict := bag 'my-file.txt'.IO.words;
say "Most common words: "%dict.sort(-*.value).head: 5;

方法 lines§

method lines(IO::Path:D: :$chomp = True:$enc = 'utf8':$nl-in = ["\x0A""\r\n"], |c --> Seq:D)

打开调用者并返回其 lines

该行为等同于 打开 调用者指定的文件,将 :$chomp:$enc:$nl-in 参数转发到 IO::Handle.open,然后在该句柄上调用 IO::Handle.lines,将任何剩余参数转发到该方法,并返回结果 Seq

注意:行是惰性准备的,底层使用的句柄在返回的 Seq 完全具体化 之前不会关闭,因此请确保它具体化,否则会泄漏打开的文件句柄。(提示:使用 $limit 参数

say "The file contains ",
  '50GB-file'.IO.lines.grep(*.contains: 'Raku').elems,
  " lines that mention Raku";
# OUTPUT: «The file contains 72 lines that mention Raku␤» 

例程 slurp§

multi method slurp(IO::Path:D: :$bin:$enc)

读取文件的所有内容,并将其作为 Buf(如果 :$binTrue)返回,如果不是,则作为使用 :$enc 编码(默认为 utf8)解码的 Str 返回。之后将关闭文件。有关 :$enc 的有效值,请参见 &open

方法 spurt§

method spurt(IO::Path:D: $data:$enc:$append:$createonly)

打开路径以进行写入,并将所有 $data 写入其中。之后将关闭文件。如果由于任何原因无法成功,将 fail$data 可以是任何 Cool 类型或任何 Blob 类型。参数如下

  • :$enc — 数据的字符编码。采用与 IO::Handle.open:$enc 相同的值。默认为 utf8。如果 $dataBlob,则忽略。

  • :$append — 以 append 模式打开文件,保留现有内容,并将数据追加到文件末尾。

  • :$createonly — 如果文件已存在,则 fail

method spurt(IO::Path:D:)

从 Rakudo 编译器的 2020.12 版本开始,还可以不带任何数据调用 spurt 方法。这将创建一个空文件,或截断给定路径处的任何现有文件。

方法 chdir§

multi method chdir(IO::Path:D: IO $path|c)
multi method chdir(IO::Path:D: Str() $path:$d = True:$r:$w:$x)

与名称相反,.chdir 方法不会更改任何目录,而只是将给定的 $path 与调用者连接,并返回结果 IO::Path。可以通过提供 :d:r:w:x Bool 命名参数来执行可选的文件测试;当设置为 True 时,它们将分别执行 .d.r.w.x 测试。默认情况下,只有 :d 设置为 True

方法 mkdir§

method mkdir(IO::Path:D: Int() $mode = 0o777 --> IO::Path:D)

创建新目录,包括其父目录(类似于带有 -p 选项的 *nix 实用程序 mkdir)。也就是说,如果 mkdir "foo/bar/ber/meow" 不存在,它还将创建 foofoo/barfoo/bar/ber 目录。

如果成功,返回指向新创建目录的 IO::Path 对象;如果无法创建目录,则使用 X::IO::Mkdir 失败

另请参阅 mode 以了解 $mode 的说明和有效值。

例程 rmdir§

sub    rmdir(*@dirs --> List:D)
method rmdir(IO::Path:D: --> True)

删除调用者,或在子表单中删除给定列表中提供的所有目录,该列表可以包含任何 Cool 对象。仅适用于空目录。

方法表单在成功时返回 True,如果无法删除目录(例如,目录不为空或路径不是目录),则返回类型为 X::IO::RmdirFailure。子例程表单返回成功删除的目录列表。

要删除非空目录,请参阅 File::Directory::Tree 模块中的 rmtree

方法 chmod§

method chmod(IO::Path:D: Int() $mode --> Bool)

将文件或目录的 POSIX 权限更改为 $mode。成功时返回 True;失败时,使用 X::IO::Chmod 失败

模式应为遵循 标准数字表示法 的整数,最好写成八进制数

'myfile'.IO.chmod(0o444);          # make a file read-only 
'somedir'.IO.chmod(0o777);         # set 0777 permissions on a directory 

确保您不会意外地将八进制数字作为十进制数(或包含十进制数的字符串)传递

'myfile'.IO.chmod:  '0444';        # BAD!!! (interpreted as mode 0o674) 
'myfile'.IO.chmod: '0o444';        # OK (an octal in a string) 
'myfile'.IO.chmod:  0o444;         # Also OK (an octal literal) 

例程 rename§

method rename(IO::Path:D: IO() $to:$createonly = False --> Bool:D)
sub    rename(IO() $fromIO() $to:$createonly = False --> Bool:D)

重命名文件或目录。成功时返回 True;如果 :$createonlyTrue 并且 $to 路径已存在或由于其他原因导致操作失败,则使用 X::IO::Rename 失败

注意:某些重命名操作始终会失败,例如当新名称位于不同的存储设备上时。另请参阅:move

例程 copy§

method copy(IO::Path:D: IO() $to:$createonly --> Bool:D)
sub    copy(IO() $fromIO() $to:$createonly --> Bool:D)

复制文件。成功时返回 True;如果 :$createonlyTrue 并且 $to 路径已存在或由于其他原因导致操作失败(例如当 $to$from 是同一文件时),则使用 X::IO::Copy 失败

例程 move§

method move(IO::Path:D: IO() $to:$createonly --> Bool:D)
sub    move(IO() $fromIO() $to:$createonly --> Bool:D)

复制文件,然后删除原始文件。如果删除失败,则可能最终得到该文件的两个副本。成功时返回 True;如果 :$createonlyTrue 并且 $to 路径已存在或由于其他原因导致操作失败(例如当 $to$from 是同一文件时),则使用 X::IO::Move 失败

为避免复制,如果文件位于同一存储设备上,您可以使用 rename。它还可以与目录一起使用,而 move 则不行。

方法 Numeric§

method Numeric(IO::Path:D: --> Numeric:D)

.basename 强制转换为 Numeric。如果基本名称不是数字,则使用 X::Str::Numeric 失败

方法 Int§

method Int(IO::Path:D: --> Int:D)

.basename 强制转换为 Int。如果基本名称不是数字,则使用 X::Str::Numeric 失败

method symlink(IO::Path:D $target: IO() $linkBool :$absolute = True --> Bool:D)
sub    symlink(      IO() $targetIO() $linkBool :$absolute = True --> Bool:D)

为现有的 $target 创建新的符号链接 $link。成功时返回 True;如果无法创建符号链接,则使用 X::IO::Symlink 失败。如果 $target 不存在,则创建一个悬空符号链接。

symlink 默认使用绝对路径创建符号链接。要创建相对符号链接,请将 absolute 参数设置为 False,例如 :!absolute。此标志在 Rakudo 版本 2020.11 中引入。

要创建硬链接,请参阅 link

注意:在 Windows 上,创建符号链接可能需要提升的权限。

method link(IO::Path:D $target: IO() $link --> Bool:D)
sub    link(      IO() $targetIO() $link --> Bool:D)

为现有的 $target 创建一个新的链接 $link。如果成功,则返回 True;如果无法创建硬链接,则使用 X::IO::Link 失败。要创建符号链接,请参阅 symlink

method unlink(IO::Path:D: --> True)
sub    unlink(*@filenames --> List:D)

删除所有指定的文件、链接或符号链接,并具有执行此操作的权限。请参阅 rmdir 以删除目录。

子例程形式返回列表中所有文件的名称,不包括文件系统引发错误的文件;由于尝试删除不存在的文件不会在该级别引发任何错误,因此此列表将包括列表中不存在的文件的名称。

方法形式在成功时返回 True,或者如果无法完成操作,则使用 X::IO::Unlink 失败。如果要删除的文件不存在,则例程将其视为成功。

'foo.txt'.IO.open(:w).close;
'bar'.IO.mkdir;
say unlink <foo.txt  bar  not-there.txt># OUTPUT: «[foo.txt not-there.txt]␤» 
# `bar` is not in output because it failed to delete (it's a directory) 
# `not-there.txt` is present. It never existed, so that's deemed a success. 
 
# Method form `fail`s: 
say .exception.message without 'bar'.IO.unlink;
# OUTPUT: «Failed to remove the file […] illegal operation on a directory␤» 

routine chown§

method chown(IO::Path:D: :$uid:$gid --> True)
sub    chown(*@filenames:$uid:$gid --> List:D)

在 Rakudo 编译器的 2022.12 版本中可用。

更改所有指定的文件、链接或符号链接的所有者和/或组,并具有执行此操作的权限。

子例程形式返回列表中所有文件的名称,不包括文件系统引发错误的文件。

方法形式在成功时返回 True,或者如果无法完成操作,则使用 X::IO::Chown 失败

请注意,此操作仅适用于具有“所有者”和“组”概念的操作系统,这通常在类 Unix 系统上。

say "success" if 'foo.txt'.IO.chown(:uid(137));

method IO§

method IO(IO::Path:D: --> IO::Path)

返回调用者。

method SPEC§

method SPEC(IO::Path:D: --> IO::Spec)

返回在对象创建时(隐式)指定的 IO::Spec 对象。

my $io = IO::Path.new("/bin/bash");
say $io.SPEC;                            # OUTPUT: «(Unix)␤» 
say $io.SPEC.dir-sep;                    # OUTPUT: «/␤»

文件时间戳检索§

还有 3 种方法用于获取文件(inode)的 3 个时间戳,在这些时间戳可用的操作系统上

method created§

返回一个 Instant 对象,指示文件创建的时间。

say "path/to/file".IO.created;          # Instant:1424089165 
say "path/to/file".IO.created.DateTime# 2015-02-16T12:18:50Z 

在 Rakudo 编译器的 2022.12 版本中可用。

method modified§

返回一个 Instant 对象,指示文件内容上次修改的时间。与 changed 进行比较。

say "path/to/file".IO.modified;          # Instant:1424089165 
say "path/to/file".IO.modified.DateTime# 2015-02-16T12:18:50Z 

方法 accessed§

返回一个表示文件上次访问时间戳的 Instant 对象。注意:根据文件系统挂载方式,上次访问时间可能不会在每次访问文件时更新,而只在修改后首次访问时更新。

say "path/to/file".IO.accessed;          # Instant:1424353577 
say "path/to/file".IO.accessed.DateTime# 2015-02-19T13:45:42Z 

方法 changed§

返回一个 Instant 对象,表示文件或目录的元数据上次更改的时间(例如,权限或目录中创建/删除的文件)。与 modified 进行比较。

say "path/to/file".IO.changed;           # Instant:1424089165 
say "path/to/file".IO.changed.DateTime;  # 2015-02-16T12:18:50Z 

文件权限检索§

方法 mode§

返回一个表示文件的 POSIX 权限的 IntStr 对象。结果的 Str 部分是文件权限的八进制表示,类似于 chmod(1) 实用程序接受的形式。

say ~"path/to/file".IO.mode;  # e.g. '0644' 
say +"path/to/file".IO.mode;  # e.g. 420, where sprintf('%04o', 420) eq '0644' 

此结果可用于将模式作为参数的其他方法中。

"path/to/file1".IO.chmod("path/to/file2".IO.mode);  # will change the 
                                                    # permissions of file1 
                                                    # to be the same as file2 

其他信息方法§

方法 user§

在 2021.04 Rakudo 编译器版本中可用。

user 方法返回支持此类概念的操作系统上的路径的数字用户 ID(又称“uid”)。

方法 group§

在 2021.04 Rakudo 编译器版本中可用。

group 方法返回支持此类概念的操作系统上的路径的数字组 ID(又称“gid”)。

方法 dir-with-entries§

在 2022.04 Rakudo 编译器版本中可用。

返回一个 Bool,表示路径是否是其中包含任何条目的目录。如果路径不是目录或路径不存在,则抛出异常。

say "'$_' has entries" if .d && .dir-with-entries given "path/to/dir".IO;

方法 inode§

在 2022.07 Rakudo 编译器版本中可用。

返回一个 Int 对象,表示文件系统上路径的 inode(如果文件系统支持此类概念)。

say "path/to/file".IO.inode;  # e.g. 9003678 

方法 dev§

在 2022.07 Rakudo 编译器版本中可用。

返回一个 Int 对象,表示文件系统上路径的 dev(POSIX stat 函数的 st_dev 字段)(如果文件系统支持此类概念)。

say "path/to/file".IO.dev;  # e.g. 16777233 

方法 devtype§

在 2022.07 Rakudo 编译器版本中可用。

返回一个 Int 对象,表示文件系统中路径的 devtype(POSIX stat 函数的 st_rdev 字段)(如果文件系统支持此类概念)。

say "path/to/file".IO.devtype;  # e.g. 0