如何在Perl中检测到符号链接中断?

时间:2021-11-09 00:04:37

I would like to remove a broken symlink in a directory using Perl.

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

In my mind I just had to list the file of a directory and test is this a symlink (-l) and if it returns false just unlink it.

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

But it appears that when using readir to list all files my broken symlinks are not recoganized as a file. Because my link is pointing to nothing I understand why.

但似乎当使用readir列出所有文件时,我的破坏的符号链接不会被识别为文件。因为我的链接指向什么,我理解为什么。

Then : How can I detect if a symlink is broken in Perl ?

那么:我如何检测Perl中的符号链接是否被破坏?

Thank you,

谢谢,

UPDATE

UPDATE

All the file in $myDir are symlinks, either valid or broken. When I display @files I only get a list of valid symlink.

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

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

6 个解决方案

#1


8  

There are two main relevant system calls, stat() and lstat(). The lstat() call will tell you that it is a symlink (but on other files, behaves the same as stat()). This allows you to determine that the name is a symlink. The stat() system call follows a symlink to its end, and tells you about the file (or directory) at the end of the link. If the stat() call fails on the symlink, then the symlink is broken or you're trying to access a directory or file where you have no permission.

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

The Perl file test operators include -l to detect whether a name is a symlink. You can use the Perl functions stat and lstat explicitly. Between these, you should be able to sort out whether a symlink is broken or not - but you should probably plan to write a function to do the job.

Perl文件测试运算符包括-l,用于检测名称是否为符号链接。您可以显式使用Perl函数stat和lstat。在这些之间,您应该能够理清符号链接是否被破坏 - 但您应该计划编写一个函数来完成这项工作。

You probably don't need to use the readlink Perl function. Beware the underlying system readlink() call; it does not return a null-terminated string!

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

It is interesting that neither Perl nor its POSIX module supports the realpath() function. However, the PathTools module does support it. If realpath fails, on a symlink, the symlink is non-functional (aka broken).

有趣的是,Perl及其POSIX模块都不支持realpath()函数。但是,PathTools模块确实支持它。如果realpath失败,则在符号链接上,符号链接无法使用(也称为已损坏)。

#2


6  

Combining lstat with stat:

将lstat与stat结合:

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

update: it works for me...

更新:它适合我...

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

#3


4  

Here's some code I've used to remove broken links:

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

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;

Note that it's important that the directory containing the links is the current directory. readdir returns only filenames, and the links might be relative.

请注意,包含链接的目录是当前目录很重要。 readdir只返回文件名,链接可能是相对的。

#4


3  

Check for broken symlinks (checking only the top level if there are symlinks to symlinks):

检查符号链接是否损坏(如果符号链接存在符号链接,则仅检查*):

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

#5


2  

Use readlink() and stat() the result.

使用readlink()和stat()结果。

#6


1  

Using the built-in Perl glob function ? For examples:

使用内置的Perl glob函数?举些例子:

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

For a specific $dir:

对于特定的$目录:

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

#1


8  

There are two main relevant system calls, stat() and lstat(). The lstat() call will tell you that it is a symlink (but on other files, behaves the same as stat()). This allows you to determine that the name is a symlink. The stat() system call follows a symlink to its end, and tells you about the file (or directory) at the end of the link. If the stat() call fails on the symlink, then the symlink is broken or you're trying to access a directory or file where you have no permission.

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

The Perl file test operators include -l to detect whether a name is a symlink. You can use the Perl functions stat and lstat explicitly. Between these, you should be able to sort out whether a symlink is broken or not - but you should probably plan to write a function to do the job.

Perl文件测试运算符包括-l,用于检测名称是否为符号链接。您可以显式使用Perl函数stat和lstat。在这些之间,您应该能够理清符号链接是否被破坏 - 但您应该计划编写一个函数来完成这项工作。

You probably don't need to use the readlink Perl function. Beware the underlying system readlink() call; it does not return a null-terminated string!

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

It is interesting that neither Perl nor its POSIX module supports the realpath() function. However, the PathTools module does support it. If realpath fails, on a symlink, the symlink is non-functional (aka broken).

有趣的是,Perl及其POSIX模块都不支持realpath()函数。但是,PathTools模块确实支持它。如果realpath失败,则在符号链接上,符号链接无法使用(也称为已损坏)。

#2


6  

Combining lstat with stat:

将lstat与stat结合:

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

update: it works for me...

更新:它适合我...

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

#3


4  

Here's some code I've used to remove broken links:

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

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;

Note that it's important that the directory containing the links is the current directory. readdir returns only filenames, and the links might be relative.

请注意,包含链接的目录是当前目录很重要。 readdir只返回文件名,链接可能是相对的。

#4


3  

Check for broken symlinks (checking only the top level if there are symlinks to symlinks):

检查符号链接是否损坏(如果符号链接存在符号链接,则仅检查*):

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

#5


2  

Use readlink() and stat() the result.

使用readlink()和stat()结果。

#6


1  

Using the built-in Perl glob function ? For examples:

使用内置的Perl glob函数?举些例子:

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

For a specific $dir:

对于特定的$目录:

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