This site is now 100% read-only, and retired.

XML logo

recursively remove broken symlinks in bash
Posted by atrixnet on Wed 24 Sep 2008 at 16:33
Tags:
I'm sure there's some better way... but nonetheless, this works great:

for file in $(find . -type l); do if [[ "$(file $file|sed 's/.*broken.*/WOOT/')" == "WOOT" ]]; then echo "unlinking broken symlink '$file'"; unlink $file; fi; done;

How would/do you do it?

 

Comments on this Entry

Re: recursively remove broken symlinks in bash
Posted by naoliv (200.206.xx.xx) on Wed 24 Sep 2008 at 16:54
[ View Weblogs ]
From the xutils-dev package (/usr/bin/cleanlinks):

$ whatis cleanlinks
cleanlinks (1) - remove dangling symbolic links and empty directories

[ Parent ]

Re: recursively remove broken symlinks in bash
Posted by goeb (93.128.xx.xx) on Wed 24 Sep 2008 at 19:11
[ View Weblogs ]
To find broken links I use

( find / -type l 2>/dev/null |&n bsp;xargs file ) | grep 'broken sym bolic link'

With some more pipes you should be able to remove them...

[ Parent ]

Re: recursively remove broken symlinks in bash
Posted by Anonymous (78.32.xx.xx) on Sat 27 Sep 2008 at 01:00
Totally cheating, but after searching for "exist" in the GNU find man page:

find -L . -type l -print0 | xargs -0 --no-run-if-empty rm

With -L (follow symbolic links), -type l matches against the type of the link's target (recursively following links if it's a symlink to a symlink) - unless that target does not exist, in which case it matches against the link.

(The -print0 and -0 options are specific to GNU find and xargs, and allow you to operate on files with bizarre names, e.g. containing newlines, by using the \0 (NUL) character as the line separator. There are only two characters not allowed in Unix filenames - NUL and '/'.)

If that's too subtle, here's a more long-winded solution:

find . | while read -r FILE; do
if ! test -e "$FILE"; then
rm "$FILE"
fi
done

This takes advantage of the fact that bash's test builtin dereferences symlinks (you could also write this as ! [ test -e "$FILE" ] if you prefer the "[" spelling), so test -e does not believe that a dangling symlink exists.

Both of these will also delete symlinks to (symlinks to...) dangling symlinks. If this is unacceptable, you probably want to do something involving stat(1) and readlink(1) - using file(1) in a script is rarely the right answer!

[ Parent ]

Re: recursively remove broken symlinks in bash
Posted by Anonymous (84.113.xx.xx) on Wed 17 Nov 2010 at 13:41
> find -L . -type l -print0 | xargs -0 --no-run-if-empty rm

This effectively removes all symlinks, not only the broken ones.

[ Parent ]

Re: recursively remove broken symlinks in bash
Posted by Anonymous (41.185.xx.xx) on Mon 5 Dec 2011 at 14:29
Surely -L prevents that?

[ Parent ]

Re: recursively remove broken symlinks in bash
Posted by Anonymous (38.100.xx.xx) on Tue 6 Mar 2012 at 18:09
> find -L . -type l -print0 | xargs -0 --no-run-if-empty rm

Yes this removes all links. Not just broken ones. I just tested it.

[ Parent ]