Что это лучший способ для перемещения по каталогам? - PullRequest
2 голосов
/ 11 февраля 2010

Хорошо ли оба приведенных ниже примера, или это второй плохой стиль?

Случай 1: оставаться в верхнем каталоге и использовать catdir для доступа к подкаталогам

#!/usr/bin/env perl
use warnings; use strict;

my $dir = 'my_dir_with_subdir';
my ( $count, $dh );

use File::Spec::Functions;
$count = 0;

opendir $dh, $dir or die $!;
while ( defined( my $file = readdir $dh ) ) {
    next if $file =~ /^\.{1,2}$/;
    my $sub_dir = catdir $dir, $file;
    if ( -d $sub_dir ) {
        opendir my $dh, $sub_dir or die $!;
        while ( defined( my $file = readdir $dh ) ) {
            next if $file =~ /^\.{1,2}$/;
            $count++;
        }
        closedir $dh or die $!;
    }
    else {
        $count++;
    }
}

closedir $dh or die $!;
print "$count\n";

Случай 2: перейти в подкаталоги и восстановить верхний каталог перед выходом

use Cwd;
my $old = cwd;
$count = 0;
opendir $dh, $dir or die $!;
chdir $dir or die $!;
while ( defined( my $file = readdir $dh ) ) {
    next if $file =~ /^\.{1,2}$/;
    if ( -d $file ) {
        opendir my $dh, $file or die $!;
        chdir $file or die $!;
        while ( defined( my $file = readdir $dh ) ) {
            next if $file =~ /^\.{1,2}$/;
            $count++;
        }
        closedir $dh or die $!;
        chdir $dir;
    }
    else {
        $count++;
    }
}
closedir $dh or die $!;
chdir $old or die $!;
print "$count\n";

Ответы [ 3 ]

2 голосов
/ 11 февраля 2010

Ваш вопрос: стоит ли переходить в каталоги, через которые вы проходите, или оставаться в каталоге верхнего уровня.

Ответ: Зависит.

Например, рассмотрим File :: Find . Поведение по умолчанию - действительно изменять каталоги. Тем не менее, модуль также предоставляет опцию no_chdir на случай, если это нежелательно.

В случае ваших примеров, File::Find, вероятно, не подходит, потому что вы не хотите проходить через все подкаталоги, а только через один. Вот вариант File :: Slurp :: read_dir для вашего сценария.

#!/usr/bin/perl

use strict; use warnings;

use File::Slurp;
use File::Spec::Functions qw( catfile );

my ($dir) = @ARGV;

my $contents = read_dir $dir;
my $count = 0;

for my $entry ( @$contents ) {
    my $path = catfile $dir, $entry;
    -f $path and ++ $count and next;
    -d _ and $count += () = read_dir $path;
}

print "$count\n";
1 голос
/ 11 февраля 2010

Для вашего примера лучше всего перейти на подкаталоги, и в конце не возвращайтесь к исходному каталогу. Это потому, что у каждого процесса есть свой «текущий каталог», поэтому тот факт, что ваш Perl-скрипт меняет свой собственный текущий каталог, не означает, что текущий каталог оболочки изменяется; это остается неизменным.

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

0 голосов
/ 11 февраля 2010

Используйте File :: Find, как вы уже предложили:)

Почти всегда лучше использовать модуль для решения подобных задач, чем самому бросать, если вы действительно не хотите изучать ходячие режиссеры ...

...