Question

For a given folder, how can I delete all broken links within it?

I found this answer that shows how to delete one broken link, but I can't put that together in only one line. Is there a one-liner for this?

A broken symbolic is a link that points to a file/folder that doesn't exists any longer.

Was it helpful?

Solution

Here's a POSIX way of deleting all broken symbolic links in the current directory, without recursion. It works by telling find to traverse symbolic links (-L), but stopping (-prune) at every directory-or-symbolic-link-to-such.

find -L . -name . -o -type d -prune -o -type l -exec rm {} +

You can also use a shell loop. The test -L matches symbolic links, and -e matches existing files (excluding broken symlinks).

for x in * .[!.]* ..?*; do if [ -L "$x" ] && ! [ -e "$x" ]; then rm -- "$x"; fi; done

If you want to recurse into subdirectories, this technique doesn't work. With GNU find (as found on non-embedded Linux and Cygwin), you can use the -xtype predicate to detect broken symbolic links (-xtype uses the type of the target for symbolic links, and reports l for broken links).

find -xtype l -delete

POSIXly, you need to combine two tools. You can use find -type l -exec … to invoke a command on each symbolic link, and [ -e "$x" ] to test whether that link is non-broken.

find . -type l -exec sh -c 'for x; do [ -e "$x" ] || rm "$x"; done' _ {} +

The simplest solution is to use zsh. To delete all broken symbolic links in the current directory:

rm -- *(-@D)

The characters in parentheses are glob qualifiers: - to dereference symlinks, @ to match only symlinks (the combination -@ means broken symlinks only), and D to match dot files. To recurse into subdirectories, make that:

rm -- **/*(-@D)

OTHER TIPS

Simple answer based on the answer you linked (for a given directory, $DIR):

find -L $DIR -maxdepth 1 -type l -delete

For MAC, do a dry run as follows:-

DIR=<some path>
find -L $DIR -maxdepth 1 -type l -print

Now, you can prune the old symlinks as follows:-

for f in `find -L $DIR -maxdepth 1 -type l`; do unlink $f; done

From man find EXAMPLES:

find -L /usr/ports/packages -type l -exec rm -- {} +

Delete all broken symbolic links in /usr/ports/packages.

The package symlinks is pre-installed on many distributions (including Ubuntu 16.04 & Fedora 25) and has some really useful features, one of which does precisely what you're looking for:

symlinks -d ./
    -d == delete dangling links

Answer based on the accepted answer to the question question "How can I find broken symlinks":

find . -type l -! -exec test -e {} \; -print | xargs rm

You could use readlink to determine if a symlink is broken or not.

The following would list all the broken symlinks in a given directory (and subdirectories):

find . -type l -exec sh -c 'readlink -f "{}" 1>/dev/null || echo "{}"' -- "{}" \;

Replace echo with rm to get rid of the broken ones!

(I've redirected the output of readlink to /dev/null so as to avoid confusion; it'd list the target for the symlinks.)

You can try using rmlint.

First, change directory to the folder that contains broken symlinks, and then run the following commands to find bad symlinks pointing nowhere:

rmlint --types="badlinks"

Then rmlint will create a bash script rmlint.sh in your current directory and print a list of bad symlinks in your terminal. To delete all the bad symlinks in your current directory, you can run

./rmlint.sh

Not exactly one liner, but it is very easy to use.

This answer is based on @sanmiguel's but with fd

fd -tl -L $DIR -X rm
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top