Perl, чтение директории и получение stat () для каждого файла - PullRequest
1 голос
/ 11 апреля 2011

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

Ответы [ 2 ]

7 голосов
/ 11 апреля 2011

Вам нужно будет передать полный путь к файлу в функцию stat (). В данный момент вы просто передаете имя файла, поэтому скрипт будет искать его в текущем каталоге.

Другими словами, сделайте это:

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
         $atime,$mtime,$ctime,$blksize,$blocks) = stat("$dirname/$filename");
0 голосов
/ 11 апреля 2011

Как уже упоминалось, проблема в том, что вы пытаетесь работать с файлами в $dirname только с именем файла (согласно документации readdir). Без полного пути 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. Примечание: я не проверял этот код для этого случая. Я часто использую этот метод. Это должно решить проблему, и это переносимо!

...