SUMMARY: Finding Broken Links

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