如何检测Perl中的符号链接是否已断开?

pdsfdshx  于 2023-01-31  发布在  Perl
关注(0)|答案(7)|浏览(176)

我想使用Perl删除目录中的一个损坏的符号链接。
在我看来,我只需要列出一个目录的文件,并测试这是一个符号链接(-l),如果它返回false,只是取消链接。
但是当使用readir列出所有文件时,我的符号链接没有被识别为文件,因为我的链接没有指向任何东西,我明白为什么。

    • 然后**:我如何检测Perl中的符号链接是否断开?

谢谢你,

    • 更新**

所有在$myDir中的文件都是符号链接,不管是有效的还是无效的。当我显示@files时,我只得到一个有效符号链接的列表。

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

ttp71kqs1#

有两个主要的相关系统调用stat() and lstat()lstat()调用将告诉您它是一个符号链接(但在其他文件上,行为与stat()相同)。这允许您确定名称是符号链接。stat()系统调用跟随符号链接直到其结束,并告诉你链接末尾的文件(或目录)。如果stat()调用在符号链接上失败,那么符号链接就被破坏了,或者你试图访问一个你没有权限的目录或文件。
Perl的file test操作符包括-l来检测一个名称是否是符号链接。你可以显式地使用Perl函数statlstat。在这两个函数之间,你应该能够区分出一个符号链接是否断开了--但是你可能应该计划写一个函数来完成这项工作。
您可能不需要使用readlink Perl函数,但要注意底层系统readlink()调用;它不会返回以null结尾的字符串!
有趣的是,Perl和它的POSIX模块都不支持realpath()函数,但是PathTools模块支持它,如果realpath失败,在符号链接上,符号链接是不起作用的(又名中断)。

gcxthw6b

gcxthw6b2#

lstatstat结合使用:

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
ekqde3dh

ekqde3dh3#

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

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

6kkfgxo0

6kkfgxo04#

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

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";
        }
    }
}
sh7euo9m

sh7euo9m5#

使用readlink()stat()作为结果。

gstyhher

gstyhher6#

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

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

对于特定的$dir

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

cnh2zyt37#

断开的符号链接是指不存在(!-e)的链接(-l)

perl -e 'print "broken: $_\n" for grep { -l and ! -e } glob("*");'

相关问题