我具有以下文件夹结构(作为最小示例):
dir
├── a
│ ├── b
│ │ ├── c.txt
│ │ └── d.txt
│ └── c
│ └── q.txt
├── b
│ ├── bb.txt
│ └── d
│ └── dd.txt
└── q.txt
我想查找所有.txt
个文件,但使用File::Find::Rule
从搜索中排除dir/b
中的所有内容(我知道我可以使用File::Find
轻松地做到这一点,但这需要大量重构我的代码。
我尝试了以下操作:
use feature qw(say);
use strict;
use warnings;
use File::Find::Rule;
my $dir = 'dir';
my @files = File::Find::Rule->or(
File::Find::Rule->directory->mindepth(1)->maxdepth(1)
->name( 'b' )->prune->discard,
File::Find::Rule->name('*.txt'),
)->in( $dir );
say for @files;
输出:
dir/q.txt
dir/a/c/q.txt
预期输出:
dir/q.txt
dir/a/b/d.txt
dir/a/b/c.txt
dir/a/c/q.txt
maxdepth()
函数内部似乎没有mindepth()
和or()
这样的功能。
答案 0 :(得分:4)
与find
命令行工具一样,maxdepth
并没有限制匹配的发生位置。它限制了实际遍历。
maxdepth( $level )
在起点以下最多降低
$level
(非负整数)级目录。
就像find
命令行工具一样,mindepth
可以防止在一定深度之前执行所有测试。
mindepth( $level )
请勿以小于
$level
(非负整数)的水平进行任何测试。
鉴于他们的所作所为,它们会影响整个搜索。因此,使用外部规则对象的mindepth
和maxdepth
并不奇怪,而其他规则对象则被忽略。 [1]
此处可以使用与find
命令行工具相同的解决方案。
find
:
$ find dir -wholename dir/b -prune -o -name '*.txt' -print
dir/a/b/c.txt
dir/a/b/d.txt
dir/a/c/q.txt
dir/q.txt
File :: Find :: Rule:
$ perl -MFile::Find::Rule -e'
my ($dir) = @ARGV;
CORE::say for
File::Find::Rule
->or(
File::Find::Rule->exec(sub { $_[2] eq "$dir/b" })->prune->discard,
File::Find::Rule->name("*.txt"),
)
->in($dir);
' dir
dir/q.txt
dir/a/b/c.txt
dir/a/b/d.txt
dir/a/c/q.txt
另一种方法是使用File :: Find :: Rule构建要搜索的目录列表,然后使用File :: Find :: Rule的另一种用法搜索这些目录。 (相当于find ... -print0 | xargs -0 -I{} find {} ...
的Perl。)
find
命令行实用程序以不同的方式处理放错位置的输入。
$ find dir -type d -mindepth 1 -maxdepth 1 -name b -prune -o -name '*.txt' -print
find: warning: you have specified the -mindepth option after a non-option argument (, but options are not positional (-mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.
find: warning: you have specified the -maxdepth option after a non-option argument (, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.
dir/q.txt