Найти символическую ссылку, используя Find в Perl - PullRequest
0 голосов
/ 30 августа 2018

У меня возникла проблема с тем, как найти символическую ссылку в каталоге с помощью библиотеки поиска, ее невозможно найти, и я очень новичок в использовании Perl.

use strict;
use warnings;
use File::Find::Rule;
use File::Find;
use File::Copy;

my @files = File::Find::Rule->file()
                            ->name( 'table.txt' )
                            ->in( '/a/b/c' );
for my $file (@files)   
{

    print "\nfile: $file\n";

Предположительно, существует другой каталог, содержащий указанный файл, table.txt, но это символическая ссылка / a / b / d, но символическая ссылка отсутствует при выводе на печать.

1 Ответ

0 голосов
/ 30 августа 2018

Файл File :: Find :: Rule реализует -X файловые тесты в качестве методов. Тот, который проверяет, является ли запись символической ссылкой (-l), называется symlink.

В моем прочтении вопроса вы не знаете название этого каталога (иначе зачем «находить» в нем файл?), За исключением того, что это символическая ссылка. Затем вам нужно сначала найти каталоги, которые являются символическими ссылками, а затем найти файлы в них. Для выполнения этой второй задачи вам необходимо указать модулю перейти по ссылкам.

Я использую тестовую структуру на диске

test_find/a/c/c.txt
test_find/a/b/b.txt
test_find/is_link  -> a/c  ("is_link" is a symbolic link to "a/c")

и из каталога прямо над ним я запускаю программу

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

use File::Find::Rule;

my $top_dir = shift @ARGV || './test_find';

my @symlink_dirs = File::Find::Rule->directory->symlink->in($top_dir);

foreach my $dir (@symlink_dirs) {
    my @files = File::Find::Rule->file->extras({follow => 1})->in($dir);
    say "in $dir: @files";
}

который печатает

in test_find/is_link: test_find/is_link/c.txt

Обратите внимание, что программа найдет все файлы в всех каталогах, которые являются символическими ссылками. Написание явного цикла, как указано выше, позволяет добавить код, чтобы решить, какие из каталогов symlink действительно искать. Если вы не возражаете, просматривая их все, вы можете просто сделать

my @files = File::Find::Rule->file->extras({follow => 1})->in(@symlink_dirs);

Информацию о возможностях ограничения поиска с использованием того, что вы знаете о каталоге / файле, смотрите в документации.


Если каталог ссылок находится в иерархии, не включающей цель, просто выполните поиск в этой иерархии.

С тестовой структурой

other_hier/is_link  -> ../test_find/a/c
test_find/a/c/c.txt

вам нужно только сказать ему, чтобы перейти по ссылкам

my @all_files = File::Find::Rule  # may use linebreaks and spaces
    -> file
    -> extras({ follow => 1 })
    -> in('other_hier');

При добавлении к вышеуказанной программе и распечатке это добавляет

another/is_link/c.txt

Конечно, вы можете заменить литерал 'other_hier' на $top_dir и вызвать программу с аргументом other_hier (и сделать этот каталог other_hier и ссылку в нем).

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

...