Perl,读取目录并获取每个文件的 stat()

发布于 2024-10-31 16:00:23 字数 741 浏览 6 评论 0原文

在 Perl 中,当我尝试在循环中读取 dir 并对每个文件执行 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);

In Perl, When I'm trying to read dir in a loop, and perform for each file stat() in order to get $size and $mode, I get wrong data!

For example, I just created simple text file and it shows me it has permission 0000 and no size.

Perl Code:

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十六岁半 2024-11-07 16:00:23

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

换句话说,执行以下操作:

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

You will need to pass the full filepath to the stat() function. At the moment you are just passing a filename, so the script will look in its current directory for this file.

In other words, do this:

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
         $atime,$mtime,$ctime,$blksize,$blocks) = stat("$dirname/$filename");
春庭雪 2024-11-07 16:00:23

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

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

$dirname中的文件进行操作的另一种方法是将工作目录更改为有问题的目录,操作后返回到原来的目录。我最喜欢的 cd 方式是 File::chdir 模块,它创建与当前工作目录绑定的标量 $CWD。当它被本地化到一个块并更改为您的相关目录时,这正是我所描述的。然后你可以做类似的事情:

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被恢复。注意:我还没有针对这种情况测试此代码。我经常使用这个方法。它应该可以解决这个问题,而且它是便携式的!

As mentioned by others, the problem is that you are trying to operate on files in $dirname with only the file name (as per the readdir documentation). Without the full path, stat cannot find the file.

One could concatenate the directory to each file name and perhaps even make the result absolute (see my comment to the other answer), but this is a pain in the neck.

The other way to operate on files in $dirname is to change the working directory to the directory in question, operate and then return to the original. My favorite way to cd is the File::chdir module, which creates the scalar $CWD which is tied to the current working directory. This does exactly what I described when it is made local to a block and changed to your directory in question. Then you can do something like:

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");
        }
    }

}

After the block, the original cwd is restored. Note: I have not tested this code for this case. I use this method often. It should fix the problem, and it's portable!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文