Как мне использовать $ File :: Find :: prune? - PullRequest
4 голосов
/ 05 сентября 2010

Мне нужно отредактировать файлы cue в первом каталоге, а не идти рекурсивно в подкаталоги.

find(\&read_cue, $dir_source);
sub read_cue {
    /\.cue$/ or return;

    my $fd = $File::Find::dir;
    my $fn = $File::Find::name; 
    tie my @lines, 'Tie::File', $fn
      or die "could not tie file: $!";

    foreach (@lines) {
        s/some substitution//;
    }

    untie @lines;
}

Я пробовал варианты

$File::Find::prune = 1;
return;  

но безуспешно. Где я должен разместить и определить $File::Find::prune?

Спасибо

Ответы [ 4 ]

7 голосов
/ 05 сентября 2010

Если вы не хотите повторяться, вы, вероятно, хотите использовать glob :

for  (glob("*.cue")) {
   read_cue($_);
}
4 голосов
/ 10 февраля 2011

Если вы хотите отфильтровать подкаталоги, возвращаемые с помощью File :: Find, вы должны использовать функцию предварительной обработки (а не переменную $ File :: Find :: prune), поскольку это дает вам гораздо больший контроль.Идея состоит в том, чтобы предоставить функцию, которая вызывается один раз для каждого каталога и передается список файлов и подкаталогов;возвращаемое значение - отфильтрованный список для передачи в требуемую функцию и (для подкаталогов) для рекурсии.

Как прокомментировали msw и Брайан, ваш пример, вероятно, будет лучше обслуживаться глобусом, но еслихотел использовать File :: Find, вы можете сделать что-то вроде следующего.Здесь функция предварительной обработки вызывает -f для каждого заданного файла или каталога, возвращая список файлов.Затем требуемая функция вызывается только для этих файлов, и File :: Find не попадает ни в один из подкаталогов:

use strict;
use File::Find;

# Function is called once per directory, with a list of files and
# subdirectories; the return value is the filtered list to pass to
# the wanted function.
sub preprocess { return grep { -f } @_; }

# Function is called once per file or subdirectory.
sub wanted { print "$File::Find::name\n" if /\.cue$/; }

# Find files in or below the current directory.
find { preprocess => \&preprocess, wanted => \&wanted }, '.';

. Это можно использовать для создания гораздо более сложных средств поиска файлов.Например, я хотел найти все файлы в каталоге проекта Java, не возвращаясь в подкаталоги, начинающиеся с «.», Такие как «.idea» и «.svn», созданные IntelliJ и Subversion.Вы можете сделать это, изменив функцию предварительной обработки:

# Function is called once per directory, with a list of files and
# subdirectories; return value is the filtered list to pass to the
# wanted function.
sub preprocess { return grep { -f or (-d and /^[^.]/) } @_; }
1 голос
/ 06 сентября 2010

Если вам нужны только файлы в каталоге без поиска в подкаталогах, вы не хотите использовать File :: Find.Простой glob , вероятно, добивается цели:

my @files = glob( "$dir_source/*.cue" );

Вам не нужна эта подпрограмма.В общем, когда вы делаете много работы для задачи, которая, по вашему мнению, должна быть простой, вы, вероятно, делаете это неправильно.:)

0 голосов
/ 05 сентября 2010

Скажем, у вас есть поддерево каталога с

/tmp/foo/file.cue
/tmp/foo/bar/file.cue
/tmp/foo/bar/baz/file.cue

Запуск

#! /usr/bin/perl

use warnings;
use strict;

use File::Find;

sub read_cue {
  if (-f && /\.cue$/) {
    print "found $File::Find::name\n";
  }
}

@ARGV = (".") unless @ARGV;
find \&read_cue => @ARGV;

выходы

found /tmp/foo/file.cue
found /tmp/foo/bar/file.cue
found /tmp/foo/bar/baz/file.cue

Но если вы помните каталоги, в которых вы нашли файлы cue

#! /usr/bin/perl

use warnings;
use strict;

use File::Find;

my %seen_cue;
sub read_cue {
  if (-f && /\.cue$/) {
    print "found $File::Find::name\n";
    ++$seen_cue{$File::Find::dir};
  }
  elsif (-d && $seen_cue{$File::Find::dir}) {
    $File::Find::prune = 1;
  }
}

@ARGV = (".") unless @ARGV;
find \&read_cue => @ARGV;

вы получаете только файл метки верхнего уровня:

found /tmp/foo/file.cue

Это потому, что $File::Find::prune эмулирует опцию -prune find, которая влияет на каталог обработку:

-prune

True; если файл является каталогом, не спускайтесь в него.

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