Найти файл в Perl - пропустить разрешение запрещено - PullRequest
1 голос
/ 21 сентября 2019

Попытка использовать скрипт Perl ниже, чтобы найти полный путь скрипта в подкаталогах.Необходимо пропустить папки с запрещенными правами, в то время как в определенном подкаталоге происходит сбой при отказе в разрешении.

Как я могу продолжить работу после проблемы с отказом в разрешении?

use File::Find;

my @files;
my @dirpath=qw(/app/welogic/);
 find(sub {
           push @files,$File::Find::name if (-f $File::Find::name      and /\wlst.sh$/);
      }, @dirpath);

1 Ответ

3 голосов
/ 21 сентября 2019

Permission denied (для cd) - это только предупреждение для меня (проверено с помощью хука $SIG{__WARN__}, как показано ниже), поэтому программа не убивается.

Однако поискэто мешает, я подозреваю, что в операции find

Кроме того, для каждого найденного каталога он будет chdir() в этом каталоге и продолжит поиск,вызывая функцию &wanted для каждого файла или подкаталога в каталоге.

и, по-видимому, после срыва chdir поиск завершается неудачно, и я не получаю результатов.

Я нахожуДва способа обойти это: использовать параметр preprocess для фильтрации каталогов или отключить chdir.

- Использовать параметр preprocess для фильтрации каталогов с неправильными разрешениями

Опция preprocess вызывает указанную пользователем подпрограмму, которая получает список записей (в текущем каталоге, подлежащих обработке) и должна возвращать список записей, которые затем будут обработаны.

Таким образом, мы можем проверить @_ на наличие каталогов с неправильными разрешениями и исключить их из списка возврата, чтобы они никогда не пытались

use warnings;
use strict;
use feature 'say';

use File::Find;

my @dirpath = @ARGV ? @ARGV : die "Usage: $0 dir-list\n";

my @files;

find( { 
    wanted => sub { 
        push @files, $File::Find::name 
            if -f $File::Find::name and /\.txt$/ 
    },  
    preprocess => sub { 
        #say "--> Reading: $File::Find::dir";         
        return grep { not (-d and (not -x or not -r)) } @_; 
    }
} , $dirpath); 

say for @files;

В операторе return мы отфильтровываем каталогикоторые не исполняются или не читаются.См. -X (filetest) операторы .Это утверждение можно переписать для печати имен для ведения журнала и т. Д.

- Отключить chdir -ing с помощью опции no_chdir

use warnings;
use strict;
use feature 'say';

use File::Find;

$SIG{__WARN__} = sub { warn "WARN: @_" };  # identify the warnings

sub bad_perm {
    push @files, $File::Find::name 
        if (-f $File::Find::name and /\.txt$/);
};

my @dirpath = @ARGV ? @ARGV : die "Usage: $0 dir-list\n";

my @files;

find( { no_chdir => 1, wanted => \&bad_perm }, @dirpath );

say for @files;

, которую я делаюнебольшая иерархия файлов и каталогов, также содержащая каталог, созданный пользователем root с правами доступа chmod go-rwx (для которых я должным образом получаю ошибки, в зависимости от того, как я пытаюсь прикоснуться к нему как к пользователю).

Теперь поиск работает нормально и собирает правильный список (.txt) файлов.

Наряду с этим выводится предупреждение, теперь для opendir

Can't opendir(tmp/this_belongs_to_root): Permission denied

Предупреждением можно управлять, как вам угодно, в подпрограмме $SIG{__WARN__}.Если вы не хотите видеть это предупреждение, повторно отправьте предупреждения для всех остальных, кроме него, например,

$SIG{__WARN__} = sub { 
    warn @_  unless $_[0] =~ /^Can't opendir\(.*?: Permission denied/;
};

См. % SIG переменная

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...