Jil*_*448 2 perl file find rule
我试图将子文件夹的名称(非递归)复制到使用File::Find::Rule. 我还想排除数组中提到的目录名称@exclude_dirs
#!/usr/bin/perl
use strict;
use warnings;
use File::Find::Rule;
use Data::Dumper;
my $basedir      = "C:\/Test";
my @exclude_dirs = qw( dir1_excl dir2_excl );
my @subdirs = File::Find::Rule
    ->directory()
  # ->name(@exclude_dirs)->prune->discard, File::Find::Rule->new 
    ->maxdepth(1)
    ->in( $basedir );
print Dumper(\@subdirs);
$VAR1 = [
          'dir1',
          'dir2',
          'dir3'
        ]
$VAR1 = [
          'C:/Test',
          'C:/Test/dir1',
          'C:/Test/dir1_excl',
          'C:/Test/dir2',
          'C:/Test/dir2_excl',
          'C:/Test/dir3'
        ]
你想做什么:
my @subdirs =
     File::Find::Rule
        ->mindepth(1)
        ->maxdepth(1)
        ->directory
        ->or(
            File::Find::Rule
                ->name(@exclude_dirs)
                ->discard
                ->prune,
            File::Find::Rule
                ->new
          )
        ->in($basedir);
可能的优化:
my @subdirs =
     File::Find::Rule
        ->mindepth(1)
        ->maxdepth(1)
        ->or(
            File::Find::Rule
                ->name(@exclude_dirs)
                ->discard
                ->prune,
            File::Find::Rule
                ->directory
          )
        ->in($basedir);
也就是说,您只需要以下内容:
my @subdirs =
    File::Find::Rule
        ->mindepth(1)
        ->maxdepth(1)
        ->not_name(@exclude_dirs)
        ->directory
        ->in($basedir);
所有这些都返回完整路径,因此您需要跟进
s{^\Q$basedir\E/}{} for @subdirs;
通常,我会改用 FFR,readdir因为使用readdir时间更长、更复杂且更容易出错。但在这种情况下,它是边缘。
my @subdirs;
{
   my %exclude_dirs = map { $_ => 1 } '.', '..', @exclude_dirs;
   opendir(my $dh, $basedir)
      or die("Can't read dir \"$basedir\": $!\n");
   while (my $fn = readdir($dh)) {
      next if $exclude_dirs{$fn};
      my $qfn = "$basedir/$fn";
      if (!stat($qfn)) {
         warn("Skipping \$qfn\": Can't stat: $!\n");
         next;
      }
      push @subdirs, $fn if -d _;
   }
}