我正在尝试枚举目录内容并检查那里的文件大小(没有递归)。所以我opendir
/ readdir
通过目录,跳过某些类型的文件(目录等),并使用像my $size = -s "$file_path
这样的东西获取当前文件的大小。
但是,我有一个奇怪的情况 - 在一个目录中我无法获得任何文件的大小(包含所有.exe
文件)。相同的程序在另一个目录(.txt
文件,.pl
和类似文件)上运行正常。
如果我将一些.exe
文件从第一个目录复制到另一个目录,则其大小已正确确定。
如果我再次在第一个目录上运行该程序,则正确确定复制的.exe
的大小,其他所有程序仍然失败。所以这似乎是一些奇怪的缓存问题。
知道为什么会这样吗?
修改:通过-f
检查,尺寸检查不起作用的.exe
文件不是plain files
。但是,如果我只是从那个目录中复制它们,它们就会变成普通文件。然后尺寸检查工作
用于枚举文件的代码部分:
my $dir_handle;
my $dir_entry;
my $retVal = opendir($dir_handle, "$path");
if (!$retVal)
{
print "Unable to open directory. \n$!";
exit(0);
}
while ($dir_entry = readdir($dir_handle))
{
print "Current file: $dir_entry \n";
next if (! -f $dir_entry);
my $size_bytes = -s "$dir_entry";
if ($size_bytes)
{
print "Size: $size_bytes \n";
}
}
closedir($dir_handle);
答案 0 :(得分:2)
readdir()
仅返回文件名 ,并且不包含路径信息 - 因此如果目录与当前工作目录不同,则会失败。
您想要包含路径:
while ($dir_entry = readdir($dir_handle))
{
print "Current file: $dir_entry \n";
next if (! -f "$path/$dir_entry");
my $size_bytes = -s "$path/$dir_entry";
if ($size_bytes)
{
print "Size: $size_bytes \n";
}
}
(是的,使用Unix风格的路径分隔符在这里工作正常;如果你喜欢转义,可以随意使用\
)
答案 1 :(得分:1)
readdir
仅返回每个目录条目的名称。它不包括正在读取的目录的路径。例如,如果您正在阅读/var/tmp
并且该目录包含名为foo
的文件,则readdir将返回foo
,而不是/var/tmp/foo
。
要检查目录条目是文件还是获取其大小,您必须提供文件的完整路径名,包括目录部分。除非您在当前目录中专门调用readdir
,否则您需要将每个文件名转换为路径名:
while ($dir_entry = readdir($dir_handle))
{
my $pn = $path . '/' . $dir_entry;
print "Current file: $pn \n";
next if (! -f $pn);
my $size_bytes = -s $pn;
...
}
答案 2 :(得分:0)
如前所述,您的错误是在文件操作期间不包括路径信息。
我建议使用Path::Class
使您的文件和目录操作跨平台兼容,但也要自动处理这样的问题:
use strict;
use warnings;
use Path::Class;
my $path = '.';
my $dir = dir($path);
for my $child ( $dir->children ) {
printf "Current file: %s\n", $child->basename;
next if !-f $child;
if ( my $size = -s $child ) {
print "Size: $size\n";
}
}