我有点困惑。我希望-f等于!-d
但似乎并非如此。我尝试检查文件是否为目录。
use File::Find;
find (\&found, ".");
sub found ()
{
my $fn = $File::Find::name;
if( ! -d $fn)
{
print "\n1 " . $fn; # a file
}
else
{
print "\n0 " . $fn; # a directory
}
}
Run Code Online (Sandbox Code Playgroud)
结果!-d 是有关测试目录的期望。
0 .
1 ./Whatever.mp3
1 ./x.pl
0 ./bb
1 ./bb/Whatever.mp3
0 ./aa
1 ./aa/Whatever.mp3
Run Code Online (Sandbox Code Playgroud)
-f的结果是意外的。
0 .
1 ./Whatever.mp3
1 ./x.pl
0 ./bb
0 ./bb/Whatever.mp3 # ???
0 ./aa
0 ./aa/Whatever.mp3 # ???
Run Code Online (Sandbox Code Playgroud)
默认情况下,find在调用回调之前更改为包含文件的目录。
这意味着./bb/Whatever.mp3您应该在通过时通过Whatever.mp3。结果,两个-f和-d都返回undef信号以指示发生了错误。
$File::Find::name包含相对于原始CWD的文件路径。另一方面,$_包含相对于CWD的文件路径。这就是您应该使用的。
use File::Find;
find({ wanted => \&found, no_chdir => 1 }, ".");
sub found {
if (!stat($_)) {
warn("Can't stat \"$_\": $!\n");
return;
}
if (-d _) {
print "0 $_\n; # A directory
} else {
print "1 $_\n"; # Some other kind of file
}
}
Run Code Online (Sandbox Code Playgroud)
我还包括其他两个更改。
检查错误
我们可以使用
my $rv = -d $_;
if (!defined($rv)) {
warn("Can't stat \"$_\": $!\n");
return;
}
if ($rv) {
...
}
Run Code Online (Sandbox Code Playgroud)
但是,由于这些-X函数只是stat系统调用的包装器,因此我发现使用stat前检查错误并使用_其上的特殊句柄避免对进行额外的调用比较干净stat。特殊句柄_告诉-d使用对stat/ 的先前调用的结果-X。
避免不必要的来电 chdir
现在您不使用$File::Find::name,所有时间都没有必要find打电话chdir了。这是做什么的no_chdir => 1。
要回答您实际提出的问题,有两种情况-f不等于!-d。
可能性1:您无法保存stat文件。
-f并-d返回三个不同值之一:
-f)或目录(-d)-f)或目录(-d)如果提供的路径并不存在,如果你没有权限读取目录中的文件驻留,或者发生其他一些错误,都-f和!-d会undef(和$!将包含错误代码/消息)。
可能性2:文件既不是纯文件也不是目录。
纯文件(-f)和目录(-d)只是七种文件类型中的两种。以下是其他:
-l)-p)-S)-b)-c)这七个中只有一个是真实的。
完整文件类型检查示例:
stat($qfn)
or die("Can't stat \"$qfn\": $!\n");
if (-f _) { say "\"$qfn\" is a plain file."; }
elsif (-d _) { say "\"$qfn\" is a directory."; }
elsif (-l _) { say "\"$qfn\" is a symbolic link."; }
elsif (-p _) { say "\"$qfn\" is a named pipe."; }
elsif (-S _) { say "\"$qfn\" is a socket."; }
elsif (-b _) { say "\"$qfn\" is a block device."; }
elsif (-c _) { say "\"$qfn\" is a character device."; }
else { say "\"$qfn\" is of unknown type."; } # Shouldn't happen on unix systems.
Run Code Online (Sandbox Code Playgroud)