【问题标题】:Perl, Reading dir and getting stat() for each filePerl,读取目录并获取每个文件的 stat()
【发布时间】:2011-08-02 21:29:23
【问题描述】:

在 Perl 中,当我尝试循环读取 dir 并执行 for each file stat() 以获取 $size$mode 时,我得到了错误的数据!

例如,我刚刚创建了一个简单的文本文件,它显示它有权限 0000 并且没有大小。

Perl 代码:

if (!@ARGV[0]) {
    die("Za mało parametrów!\n");
}

$dirname = @ARGV[0];

opendir(DIR, $dirname) || die("Nie mogę otworzyć katalogu!\n");
while( $filename = readdir(DIR) ) {

    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
         $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);

    $perm = sprintf("%04o", $mode & 07777);
    $tmp1 = int(($size/1024));
    $tmp2 = length($filename);

    if (($tmp1 > $tmp2) && ($perm =~ /.[^5410]../)) {
        print("$filename\n");
    }
}
closedir(DIR);

【问题讨论】:

  • 在开发 Perl 代码时应始终启用警告(然后将 @ARGV[0] 更改为 $ARGV[0])。您的问题的解决方案在 readdir() 函数的文档的第二段中给出。

标签: perl stat opendir


【解决方案1】:

您需要将完整的文件路径传递给 stat() 函数。目前您只是传递一个文件名,因此脚本将在其当前目录中查找该文件。

换句话说,这样做:

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
         $atime,$mtime,$ctime,$blksize,$blocks) = stat("$dirname/$filename");

【讨论】:

  • 您真的应该使用来自File::Spec::Functionscatfile,而不是手动连接目录。此外,您可能还想使用Cwd 中的abs_path,一旦您走了这么远。
【解决方案2】:

正如其他人所提到的,问题是您试图仅使用文件名(根据 readdir 文档)对 $dirname 中的文件进行操作。如果没有完整路径,stat 将无法找到该文件。

可以将目录连接到每个文件名,甚至可以使结果绝对化(请参阅我对另一个答案的评论),但这是一件令人头疼的事情。

$dirname中的文件进行操作的另一种方法是将工作目录更改为有问题的目录,操作然后返回原来的。我最喜欢的cd 方法是File::chdir 模块,它创建了与当前工作目录相关联的标量$CWD。这完全符合我在将local 设置为一个块并更改为您的相关目录时所描述的内容。然后您可以执行以下操作:

use strict;
use warnings;

use File::chdir;

$dirname = shift @ARGV or die("Za mało parametrów!\n") ;

{
    local $CWD = $dirname; #changes the cwd to contents of $dirname

    opendir(my $dir, $CWD) || die("Nie mogę otworzyć katalogu!\n");
    while( $filename = readdir($dir) ) {

        ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
             $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);

        $perm = sprintf("%04o", $mode & 07777);
        $tmp1 = int(($size/1024));
        $tmp2 = length($filename);

        if (($tmp1 > $tmp2) && ($perm =~ /.[^5410]../)) {
            print("$filename\n");
        }
    }

}

块后,恢复原来的cwd。注意:我没有针对这种情况测试此代码。我经常使用这种方法。它应该可以解决问题,而且它是可移植的!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 2011-07-20
    • 2015-05-28
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多