Как пройти все файлы в каталоге;если в нем есть подкаталоги, я тоже хочу просматривать файлы в подкаталогах - PullRequest
7 голосов
/ 07 марта 2012
opendir(DIR,"$pwd") or die "Cannot open $pwd\n";
    my @files = readdir(DIR);
    closedir(DIR);
    foreach my $file (@files) {
        next if ($file !~ /\.txt$/i);
        my $mtime = (stat($file))[9];
        print $mtime;
        print "\n";
    }

В основном я хочу отметить временную метку всех текстовых файлов в каталоге.Если есть подкаталог, я тоже хочу включить файлы в этот подкаталог.

Может ли кто-нибудь помочь мне изменить приведенный выше код, чтобы он также включал подкаталоги.

, если я использую код нижев Windows IAM получать метки времени всех файлов, которые находятся в папках, даже за пределами моей папки

 my @dirs = ("C:\\Users\\peter\\Desktop\\folder");
    my %seen;
    while (my $pwd = shift @dirs) {
            opendir(DIR,"$pwd") or die "Cannot open $pwd\n";
            my @files = readdir(DIR);
            closedir(DIR);
            #print @files;
            foreach my $file (@files) {
                    if (-d $file and !$seen{$file}) {
                            $seen{$file} = 1;
                            push @dirs, "$pwd/$file";
                    }
                    next if ($file !~ /\.txt$/i);
                    my $mtime = (stat("$pwd\$file"))[9];
                    print "$pwd $file $mtime";
                    print "\n";
            }
    }

Ответы [ 5 ]

13 голосов
/ 07 марта 2012

File :: Find лучше всего подходит для этого. Это основной модуль, поэтому не требует установки. Этот код соответствует тому, что вы, похоже, имеете в виду

use strict;
use warnings;

use File::Find;

find(sub {
  if (-f and /\.txt$/) {
    my $mtime = (stat _)[9];
    print "$mtime\n";
  }
}, '.');

где '.' - корень дерева каталогов для сканирования; Вы можете использовать $pwd здесь, если хотите. В рамках подпрограммы Perl сделал chdir для каталога, в котором он нашел файл, $_ - для имени файла, а $File::Find::name - для полного имени файла, включая путь.

8 голосов
/ 07 марта 2012
use warnings;
use strict;

my @dirs = (".");
my %seen;
while (my $pwd = shift @dirs) {
        opendir(DIR,"$pwd") or die "Cannot open $pwd\n";
        my @files = readdir(DIR);
        closedir(DIR);
        foreach my $file (@files) {
                next if $file =~ /^\.\.?$/;
                my $path = "$pwd/$file";
                if (-d $path) {
                        next if $seen{$path};
                        $seen{$path} = 1;
                        push @dirs, $path;
                }
                next if ($path !~ /\.txt$/i);
                my $mtime = (stat($path))[9];
                print "$path $mtime\n";
        }
}
4 голосов
/ 07 марта 2012

использовать Файл :: Найти :: Правило

File :: Find :: Rule - более дружественный интерфейс для File :: Find. Позволяет создавать правила, определяющие нужные файлы и каталоги.

1 голос
/ 07 марта 2012

Вы можете использовать рекурсию: определить функцию, которая просматривает файлы и вызывает себя в каталогах.Затем вызовите функцию в верхнем каталоге.

См. Также Файл :: Найти .

0 голосов
/ 07 мая 2018

если я использую приведенный ниже код в Windows, я получаю временные метки всех файлов, которые находятся в папках даже вне моей папки

Я подозреваю, что проблема могла быть связана с каталогами . и .., которые, если бы вы попытались следовать им, взяли бы вас вверх дерево каталогов. То, что вам не хватало, было:

foreach my $file (@files) {
    # skip . and .. which cause recursion and moving up the tree
    next if $file =~ /^\.\.?$/;
    ...

Ваш скрипт также страдает от пары ошибок. $file не относится к $dir, поэтому -d $file будет работать только в текущем каталоге, а не ниже.

Вот моя исправленная версия:

use warnings;
use strict;

# if unix, change to "/";
my $FILE_PATH_SLASH = "\\";    
my @dirs = (".");
my %seen;
while (my $dir = shift @dirs) {
        opendir(DIR, $dir) or die "Cannot open $dir\n";
        my @files = readdir(DIR);
        closedir(DIR);
        foreach my $file (@files) {
                # skip . and ..
                next if $file =~ /^\.\.?$/;
                my $path = "$dir$FILE_PATH_SLASH$file";
                if (-d $path) {
                        next if $seen{$path};
                        $seen{$path} = 1;
                        push @dirs, $path;
                }
                next unless $path ~= /\.txt$/i;
                my $mtime = (stat($path))[9];
                print "$path $mtime\n";
        }
}
...