首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl文件::查找::Rule

Perl文件::查找::Rule
EN

Stack Overflow用户
提问于 2016-02-25 17:10:14
回答 2查看 1.6K关注 0票数 2

我试图使用File::Find::Rule将子文件夹的名称(非递归)复制到数组中。我还想排除数组@exclude_dirs中提到的目录名。

代码语言:javascript
复制
#!/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);

期望输出

代码语言:javascript
复制
$VAR1 = [
          'dir1',
          'dir2',
          'dir3'
        ]

电流输出

代码语言:javascript
复制
$VAR1 = [
          'C:/Test',
          'C:/Test/dir1',
          'C:/Test/dir1_excl',
          'C:/Test/dir2',
          'C:/Test/dir2_excl',
          'C:/Test/dir3'
        ]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-25 17:38:19

你想要的是:

代码语言:javascript
复制
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);

可能的优化:

代码语言:javascript
复制
my @subdirs =
     File::Find::Rule
        ->mindepth(1)
        ->maxdepth(1)
        ->or(
            File::Find::Rule
                ->name(@exclude_dirs)
                ->discard
                ->prune,
            File::Find::Rule
                ->directory
          )
        ->in($basedir);

尽管如此,你所需要的只是以下几点:

代码语言:javascript
复制
my @subdirs =
    File::Find::Rule
        ->mindepth(1)
        ->maxdepth(1)
        ->not_name(@exclude_dirs)
        ->directory
        ->in($basedir);

所有这些都会返回完整的路径,所以您需要跟踪

代码语言:javascript
复制
s{^\Q$basedir\E/}{} for @subdirs;

通常,我会使用FFR而不是readdir,因为使用readdir要长得多,复杂得多,而且更容易出错。但在这种情况下,它是边缘。

代码语言:javascript
复制
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 _;
   }
}
票数 5
EN

Stack Overflow用户

发布于 2016-02-25 18:20:20

代码语言:javascript
复制
use strict;
use warnings;

use Data::Dumper;

my $basedir      = "C:/Test";
my @exclude_dirs = qw(. .. dir1_excl dir2_excl);
my $exclude_pat  = join('|', map { quotemeta } @exclude_dirs);

opendir(my $dh, $basedir) or die $!;
my @subdirs = grep { -d "$basedir/$_" && !/^(?:$exclude_pat)\z/i } readdir($dh);
closedir($dh);

print Dumper(\@subdirs);

如果要排除的目录不像问题中所显示的那样动态,则无需在运行时构建正则表达式:

代码语言:javascript
复制
my @subdirs = grep { -d "$basedir/$_" && !/^(?:\.|\.\.|dir1_excl|dir2_excl)\z/i } readdir($dh);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35633820

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档