zoltanctoth
zoltanctoth

Reputation: 2927

How can I detect whether a symlink is broken in Bash?

I run find and iterate through the results with [ \( -L $F \) ] to collect certain symbolic links.

I am wondering if there is an easy way to determine if the link is broken (points to a non-existent file) in this scenario.

Here is my code:

FILES=`find /target/ | grep -v '\.disabled$' | sort`

for F in $FILES; do
    if [ -L $F ]; then
        DO THINGS
    fi
done

Upvotes: 66

Views: 48795

Answers (8)

datUser
datUser

Reputation: 293

On recent versions of bash (5.1.16) test -e "$link" or [[ -e "$link" ]] do not behave as expected, failing to recognize the link as broken.

I suggest using readlink(1) as well as testing for the existence of the link as follows:

if [[ ! -L "$link" ]]; then
    echo "Missing or not a symlink"
else
    readlink -q "$link"
    if [[ $? -ne 0 ]]; then
         echo "Broken"
    fi
fi

Upvotes: 1

Frank N
Frank N

Reputation: 10416

If it does qualify as a symbolic link, but is „not existing“, its a broken link.

if [[ -h $link && ! -e $link ]] ; then
    _info "$link is a BROKEN SYMLINK"
fi

REFERENCE

Upvotes: -1

Roger
Roger

Reputation: 728

# test if symlink is broken (by seeing if it links to an existing file)
if [ ! -e "$F" ] ; then
    # code if the symlink is broken
fi

Upvotes: 64

Rew Brian
Rew Brian

Reputation: 23

What's wrong with:

file $f | grep 'broken symbolic link'

Upvotes: -1

William Pursell
William Pursell

Reputation: 212664

If you don't mind traversing non-broken dir symlinks, to find all orphaned links:

$ find -L /target -type l | while read -r file; do echo $file is orphaned; done

To find all files that are not orphaned links:

$ find -L /target ! -type l

Upvotes: 2

ACyclic
ACyclic

Reputation: 6290

This finds all files of type "link", which also resolves to a type "link". ie. a broken symlink

find /target -type l -xtype l

Upvotes: 5

Aquarius Power
Aquarius Power

Reputation: 3985

this will work if the symlink was pointing to a file or a directory, but now is broken

if [[ -L "$strFile" ]] && [[ ! -a "$strFile" ]];then 
  echo "'$strFile' is a broken symlink"; 
fi

Upvotes: 12

Shawn Chin
Shawn Chin

Reputation: 86974

This should print out links that are broken:

find /target/dir -type l ! -exec test -e {} \; -print

You can also chain in operations to find command, e.g. deleting the broken link:

find /target/dir -type l ! -exec test -e {} \; -exec rm {} \;

Upvotes: 39

Related Questions