文件测试,其中 X 是下面列出的字母之一。此一元运算符接受一个参数,可以是文件名、文件句柄或目录句柄,并测试关联的文件以查看其是否满足某些条件。如果省略参数,则测试 $_
,除了 -t
,它测试 STDIN。除非另有说明,否则它对真返回 1
,对假返回 ''
。如果文件不存在或无法检查,它将返回 undef
并设置 $!
(errno)。除了 -l
测试之外,它们都遵循符号链接,因为它们使用 stat()
而不是 lstat()
(因此悬空符号链接无法检查,因此将报告失败)。
尽管名称很奇怪,但优先级与任何其他命名一元运算符相同。运算符可以是以下任何一个
-r File is readable by effective uid/gid.
-w File is writable by effective uid/gid.
-x File is executable by effective uid/gid.
-o File is owned by effective uid.
-R File is readable by real uid/gid.
-W File is writable by real uid/gid.
-X File is executable by real uid/gid.
-O File is owned by real uid.
-e File exists.
-z File has zero size (is empty).
-s File has nonzero size (returns size in bytes).
-f File is a plain file.
-d File is a directory.
-l File is a symbolic link (false if symlinks aren't
supported by the file system).
-p File is a named pipe (FIFO), or Filehandle is a pipe.
-S File is a socket.
-b File is a block special file.
-c File is a character special file.
-t Filehandle is opened to a tty.
-u File has setuid bit set.
-g File has setgid bit set.
-k File has sticky bit set.
-T File is an ASCII or UTF-8 text file (heuristic guess).
-B File is a "binary" file (opposite of -T).
-M Script start time minus file modification time, in days.
-A Same for access time.
-C Same for inode change time (Unix, may differ for other
platforms)
示例
while (<>) {
chomp;
next unless -f $_; # ignore specials
#...
}
请注意,-s/a/b/
不会执行否定替换。但是,-exp($foo)
仍然按预期工作:只有紧跟在减号后面的单个字母被解释为文件测试。
这些运算符不受上述“看起来像函数规则”的约束。也就是说,运算符后面的左括号不会影响后续代码中构成参数的代码量。将左括号放在运算符之前以将其与后续代码隔开(当然,这仅适用于优先级高于一元运算符的运算符)。
-s($file) + 1024 # probably wrong; same as -s($file + 1024)
(-s $file) + 1024 # correct
文件权限操作符-r
、-R
、-w
、-W
、-x
和-X
的解释默认情况下仅基于文件的模式以及用户的uid和gid。可能还有其他原因导致您无法实际读取、写入或执行文件:例如网络文件系统访问控制、ACL(访问控制列表)、只读文件系统和无法识别的可执行文件格式。请注意,使用这六个特定操作符来验证某个操作是否可行通常是一个错误,因为它可能会出现竞争条件。
另请注意,对于本地文件系统上的超级用户,-r
、-R
、-w
和-W
测试始终返回1,而-x
和-X
如果模式中设置了任何执行位,则返回1。因此,由超级用户运行的脚本可能需要执行stat
来确定文件的实际模式,或者暂时将其有效uid设置为其他值。
如果您使用ACL,则有一个名为filetest
的pragma,它可能比裸stat
模式位产生更准确的结果。在use filetest 'access'
下,上述文件测试将测试是否可以使用access(2)系列系统调用授予(不授予)权限。另请注意,在此pragma下,即使没有设置执行权限位(也没有任何额外的执行权限ACL),-x
和-X
测试也可能返回true。这种奇怪现象是由于底层系统调用的定义造成的。另请注意,由于use filetest 'access'
的实现,当此pragma生效时,_
特殊文件句柄不会缓存文件测试的结果。有关更多信息,请阅读filetest
pragma的文档。
-T
和-B
测试的工作原理如下。检查文件的第一个块或更多块,以查看它是否为包含非ASCII字符的有效UTF-8。如果是,则为-T
文件。否则,将检查文件相同部分的奇特字符,例如奇怪的控制代码或高位设置的字符。如果超过三分之一的字符是奇特的,则为-B
文件;否则为-T
文件。此外,在检查部分中包含零字节的任何文件都被视为二进制文件。(如果在包含LC_CTYPE
的use locale范围内执行,则奇特字符是当前区域设置中任何不可打印的字符或空格。)如果-T
或-B
用于文件句柄,则检查当前IO缓冲区而不是第一个块。-T
和-B
在空文件或测试文件句柄时处于EOF的文件上都返回true。因为您必须读取文件才能执行-T
测试,所以在大多数情况下,您希望首先对文件使用-f
,例如next unless -f $file && -T $file
。
如果任何文件测试(或stat
或lstat
操作符)被赋予由单个下划线组成的特殊文件句柄,则使用先前文件测试(或stat
操作符)的stat结构,从而节省了系统调用。(这在-t
中不起作用,您需要记住lstat
和-l
在stat结构中保留符号链接的值,而不是实际文件。)(此外,如果stat缓冲区由lstat
调用填充,则-T
和-B
将使用stat _
的结果重置它。)示例
print "Can do.\n" if -r $a || -w _ || -x _;
stat($filename);
print "Readable\n" if -r _;
print "Writable\n" if -w _;
print "Executable\n" if -x _;
print "Setuid\n" if -u _;
print "Setgid\n" if -g _;
print "Sticky\n" if -k _;
print "Text\n" if -T _;
print "Binary\n" if -B _;
从 Perl 5.10.0 开始,作为纯粹的语法糖,您可以堆叠文件测试运算符,例如 -f -w -x $file
等同于 -x $file && -w _ && -f _
。(这仅仅是花哨的语法:如果您将 -f $file
的返回值用作另一个文件测试运算符的参数,则不会发生任何特殊操作。)
可移植性问题:perlport 中的 "-X"。
为了避免让您的代码的潜在用户因神秘的语法错误而感到困惑,请在脚本开头添加类似以下内容
use v5.10; # so filetest ops can stack