Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I detect that a symlink is broken in Perl?

I would like to remove a broken symlink in a directory using 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.

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.

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

Thank you,

UPDATE

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

opendir DIR, $myDir;
my @files = grep(/$regexp/,readdir(DIR));
closedir DIR;
print "filenames : @files\n";
like image 701
Spredzy Avatar asked Jul 05 '11 09:07

Spredzy


People also ask

How do I know if a symbolic link is valid?

If the name in $1 is a valid symbolic link, then the -e test would be true. If it's a broken symbolic link, then the -e test would fail.

Is a broken symlink?

A symlink is broken (or left dangling) when the file at which it points is deleted or moved to another location. If an application's uninstallation routine doesn't work properly, or is interrupted before it completes, you might be left with broken symlinks.

How do I fix a broken symlink?

The only way to fix these broken symlinks is by deleting them. Your system contains hundreds of dangling links and no one has the time to check for these links manually. In such cases, Linux tools and commands prove to be really helpful.

How can I see symlink points?

Simplest way: cd to where the symbolic link is located and do ls -l to list the details of the files. The part to the right of -> after the symbolic link is the destination to which it is pointing. Save this answer.


2 Answers

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.

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.

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!

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).

like image 87
Jonathan Leffler Avatar answered Sep 21 '22 15:09

Jonathan Leffler


Combining lstat with 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
like image 32
salva Avatar answered Sep 19 '22 15:09

salva