Как я могу обнаружить, что символическая ссылка не работает в Perl? - PullRequest
8 голосов
/ 05 июля 2011

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

По моему мнению, я просто должен был перечислить файл каталога и проверить, является ли это символической ссылкой (-l), и если он возвращает false, просто отсоедините его.

Но похоже, что при использовании readir для вывода списка всех моих сломанных символических ссылок они не распознаются как файл. Поскольку моя ссылка ни на что не указывает, я понимаю, почему.

Тогда : Как я могу определить, не сломана ли символическая ссылка в Perl?

Спасибо,

UPDATE

Все файлы в $ myDir являются символическими ссылками, действительными или неработающими. Когда я отображаю @files, я получаю только список действительных символических ссылок.

opendir DIR, $myDir;
my @files = grep(/$regexp/,readdir(DIR));
closedir DIR;
print "filenames : @files\n";

Ответы [ 6 ]

8 голосов
/ 05 июля 2011

Существует два основных соответствующих системных вызова: stat() и lstat().Вызов lstat() скажет вам, что это символическая ссылка (но в других файлах ведет себя так же, как stat()).Это позволяет вам определить, что имя является символической ссылкой.Системный вызов stat() следует по символической ссылке до конца и сообщает вам о файле (или каталоге) в конце ссылки.Если в символьной ссылке произойдет сбой stat(), символическая ссылка будет прервана или вы пытаетесь получить доступ к каталогу или файлу, к которому у вас нет разрешения.

Файл Perl file test operatorвключите -l, чтобы определить, является ли имя символической ссылкой.Вы можете явно использовать функции Perl stat и lstat.Между ними вы должны быть в состоянии выяснить, является ли символическая ссылка неработающей или нет - но вы, вероятно, должны запланировать написание функции для выполнения этой работы.

Возможно, вам не нужно использовать readlink Функция Perl.Остерегайтесь базовой системы readlink() вызов;он не возвращает строку с нулевым символом в конце!

Интересно, что ни Perl, ни его модуль POSIX не поддерживают функцию realpath().Однако модуль PathTools поддерживает его.Если realpath терпит неудачу, на символьной ссылке символическая ссылка не работает (она не работает).

6 голосов
/ 05 июля 2011

Объединение lstat с stat:

say "dangling link at $fn" if (lstat $fn and not stat $fn);

обновление : у меня работает ...

salva@topo:~/t/dl$ perl -E 'opendir $dh, "."; say $_ for grep { !stat $_ and lstat $_ } readdir $dh'
foo
salva@topo:~/t/dl$ ls -l
total 0
-rw-rw-r-- 1 salva salva  0 2011-07-05 12:34 f
lrwxrwxrwx 1 salva salva 11 2011-07-05 12:00 fii -> /etc/shadow
lrwxrwxrwx 1 salva salva 12 2011-07-05 11:59 foo -> /etc/hjdkshf
4 голосов
/ 05 июля 2011

Вот некоторый код, который я использовал для удаления неработающих ссылок:

chdir $dir        or die;
opendir(DIR, '.') or die;

foreach my $link (readdir DIR) {
  next unless -l $link and not -e readlink($link);

  print "Removing broken link $link\n";
  unlink $link;
}

closedir DIR;

Обратите внимание, что важно, чтобы каталог, содержащий ссылки, был текущим каталогом.readdir возвращает только имена файлов, и ссылки могут быть относительными.

3 голосов
/ 05 июля 2011

Проверить наличие битых символических ссылок (проверка только верхнего уровня, если есть символические ссылки на символические ссылки):

use strict;
use warnings;
use autodie;
opendir my $dirh, '.';
while (my $file = readdir $dirh) {
    if ( -l $file ) {
        my $target = readlink $file;
        if ( ! -e $target && ! -l $target ) {
            print "$file -> $target broken\n";
        }
    }
}
2 голосов
/ 05 июля 2011

Используйте readlink() и stat() результат.

0 голосов
/ 27 декабря 2011

Используя встроенную функцию Perl glob?Например:

 @files = <*>;
 foreach $file (@files) {
   print $file . "\n";
 }

Для конкретного $dir:

 @files = <$dir*>;
 foreach $file (@files) {
   print $file . "\n";
 }
...