我如何使用$ File :: Find :: prune?

时间:2010-09-05 18:44:53

标签: perl

我需要在第一个目录中编辑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 个答案:

答案 0 :(得分:7)

如果您不想递归,可能需要使用glob

for  (glob("*.cue")) {
   read_cue($_);
}

答案 1 :(得分:4)

如果要过滤由File :: Find递归的子目录,则应使用预处理函数(而不是$ File :: Find :: prune变量),因为这样可以提供更多控制。我们的想法是提供一个每个目录调用一次的函数,并传递一个文件和子目录列表;返回值是要传递给所需函数的筛选列表,以及(对于子目录)要递归到。

正如msw和Brian所评论的那样,你的例子可能会被glob更好地服务,但如果你想使用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项目目录中的所有文件,而不是递归到以“。”开头的子目录,例如由IntelliJ和Subversion创建的“.idea”和“.svn”。您可以通过修改预处理功能来完成此操作:

# 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 /^[^.]/) } @_; }

答案 2 :(得分:1)

如果您只想要目录中的文件而不搜索子目录,则不希望使用File :: Find。一个简单的glob可能就是这个诀窍:

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

您不需要该子程序。一般来说,当你为一项你认为应该简单的任务做大量的工作时,你可能做错了。 :)

答案 3 :(得分:-1)

假设您有

目录子树
/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

     

真;如果文件是目录,请不要进入该目录。