From: Sumair Mahmood (Sumair.Mahmood@qlogic.com)
Date: Tue Apr 30 2002 - 12:15:47 EDT
QUESTION:
=========
I have a number of broken symbolic links on the file systems of
computers which I manage. I know I can find all of the symbolic
links in a given filesystem using the following :
(1) ls -l | grep '^l'
(2) find /dir -type l -exec ls -l {} \;
Is there a way, I wonder, to 'follow' a link to test to see if it
is valid? 'ls -L' isn't reporting any errors for my broken links.
I would like to throw together a Bourne script to automate the
process of finding and deleting dangling links.
P.S. I wish I did, but I don't know Perl. If we could please
limit this discussion to Unix shell scripting, I would
appreciate it!
ANSWERS:
========
(1) find /dir -type l -follow
will return "find: cannot follow symbolic link [whatever]:
No such file or directory" for each broken link.
- Alex Shephard
(2) See Figure 5 at the following PDF for a csh script
http://swexpert.com/C4/SE.C4.DEC.96.pdf
(but really, I'd rather use perl for this job...) :-)
- Darren Dunham
(3) 'test -r' fails on a hanging symlink. The /bin/sh-ism would
be something like:
if [ -h $fname ] && [ ! -r $fname ] ; then
echo "Bad symbolic link!"
fi
- Jay Lessert
(4) Here is a shell script to find broken links:
----cut here----
#!/bin/ksh
#
ls -ld * | grep '^l' | awk '{print $9}' > /tmp/linktmp.$$
for x in `cat /tmp/linktmp.$$`
do
if [ ! -e $x ]
then
echo "bogus link: $x"
fi
done
----cut here----
and here is one in Perl:
----cut here----
#!/usr/local/bin/perl
use File::Find;
find( \&wanted, '.' );
sub wanted {
-l and not -e and print "bogus link: $File::Find::name\n";
}
----cut here----
- Tim Fritz
(5) "test -s $file || ls -la $file" is the test you want in Bourne
shell syntax.
- Thomas Anders
(6) Here you go:
for link in `find . -type l `
do
cat $link > /dev/null 2> /dev/null;
if test $? -ne 0
then
echo $link
fi
done
- Chris Veenstra
(7) Something like:
find /dir -type l -exec ls -l {} \; -exec cat {} \>dev/null \;
Should throw an error for the ones that are broken
- Jim Malloy
(8) Try this:
for i in `ls -lc directory |awk '/^l/ {print $11}'`
do
echo $i
if [ -r $i ]
then
echo "$i exists"
fi
done
- Jaime Dela Rosa
(9) Perl exists for a reason:
#!/usr/bin/perl -w
use strict;
use File::Find;
sub wanted
{
my $curfil = $_;
my $curdir = $File::Find::dir;
if ( ! -l $curfil ) { return; }
#Curfil is a symlink
my $linkto = readlink($curfil);
if ( -e $linkto ) { return; }
#file it links to does not exist
print "$curdir/$curfil is a broken link (pointing to $linkto)\n";
}
#Start of script
my $top = shift @ARGV or die "Please provide a starting directory";
find(\&wanted,$top);
----------------------------
Usage:
link-test.pl /
(one argument, the directroy to start the find in).
- Thomas M. Payerle
(10) Doing this in perl, you could do the following:
#!/usr/local/bin/perl -w
use File::Find;
find(\&wanted, '/dir');
sub wanted {
return unless -l $File::Find::name; # Check only symbolic links
unless (stat($File::Find::name)){ # If the file can't be stat'd
print "Bad link for $File::Find::name\n";
}
}
- Dylan Northrup
_______________________________________________
sunmanagers mailing list
sunmanagers@sunmanagers.org
http://www.sunmanagers.org/mailman/listinfo/sunmanagers
This archive was generated by hypermail 2.1.7 : Wed Apr 09 2008 - 23:24:16 EDT