Linux 如何在Perl中检测符号链接被破坏?

Linux 如何在Perl中检测符号链接被破坏?,linux,perl,symlink,Linux,Perl,Symlink,我想使用Perl删除目录中损坏的符号链接 在我看来,我只需要列出一个目录的文件,并测试这是一个符号链接(-l),如果它返回false,只需取消链接 但当使用readir列出所有文件时,我的断开符号链接似乎不会重新组织为文件。因为我的链接没有指向任何东西,我不明白为什么 那么:如何检测Perl中的符号链接是否中断 谢谢, 更新 $myDir中的所有文件都是符号链接,有效或已断开。 当我显示@files时,我只得到一个有效符号链接的列表 opendir DIR, $myDir; my @files

我想使用Perl删除目录中损坏的符号链接

在我看来,我只需要列出一个目录的文件,并测试这是一个符号链接(-l),如果它返回false,只需取消链接

但当使用readir列出所有文件时,我的断开符号链接似乎不会重新组织为文件。因为我的链接没有指向任何东西,我不明白为什么

那么:如何检测Perl中的符号链接是否中断

谢谢,

更新

$myDir中的所有文件都是符号链接,有效或已断开。 当我显示@files时,我只得到一个有效符号链接的列表

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

以下是我用来删除断开链接的一些代码:

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
只返回文件名,链接可能是相对的。

检查是否存在断开的符号链接(如果存在指向符号链接的符号链接,则仅检查顶层):


使用
readlink()
stat()
查看结果。

有两个主要的相关系统调用。调用
lstat()
将告诉您它是一个符号链接(但在其他文件上,其行为与
stat()
相同)。这允许您确定名称是符号链接。
stat()
系统调用跟随一个符号链接到其末尾,并告诉您链接末尾的文件(或目录)。如果符号链接上的
stat()
调用失败,则符号链接已断开,或者您正试图访问您没有权限的目录或文件

Perl运算符包括
-l
,用于检测名称是否为符号链接。您可以显式地使用Perl函数和。在这两者之间,您应该能够分辨出符号链接是否损坏——但您可能应该计划编写一个函数来完成这项工作

您可能不需要使用Perl函数。注意底层系统调用;它不会返回以null结尾的字符串


有趣的是,Perl及其POSIX模块都不支持该函数。但是,该模块确实支持它。如果
realpath
在符号链接上失败,则符号链接不起作用(也称为断开)。

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

使用内置的Perl glob函数? 例如:

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

“不重新组织为文件”是什么意思?凭什么?显示你的代码。+1:关于名字的相对性的观点很好。您可以将
readdir
中的值添加到目录的名称(相对或绝对)中,然后从该名称开始工作:
下一步,除非-l“$dir/$link”而不是-e“$dir/$link”
。在那次重写中,我省略了
readlink
;我认为这没关系,因为O/S为您读取了链接。所有答案都很好。我只是用这个来解释。谢谢。如果
$dir
包含在
glob
中特殊的字符,例如空格或
*
,则这不起作用。
 @files = <*>;
 foreach $file (@files) {
   print $file . "\n";
 }
 @files = <$dir*>;
 foreach $file (@files) {
   print $file . "\n";
 }