Как использовать mindepth и maxdepth в `или` альтернативе в File :: Find :: Rule? - PullRequest
0 голосов
/ 05 октября 2018

У меня следующая структура папок (как минимальный пример):

dir
├── a
│   ├── b
│   │   ├── c.txt
│   │   └── d.txt
│   └── c
│       └── q.txt
├── b
│   ├── bb.txt
│   └── d
│       └── dd.txt
└── q.txt

Я хочу найти все .txt файлы, но исключить все в dir/b из поиска, используя File::Find::Rule (я знаю, что мог бы легко это сделать, используя 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().

1 Ответ

0 голосов
/ 06 октября 2018

Как и в случае инструмента командной строки 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.(Perl эквивалент find ... -print0 | xargs -0 -I{} find {} ....)


  1. Утилита командной строки 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
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...