Delete all broken symbolic links with a line?
Solution 1
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)
Solution 2
Simple answer based on the answer you linked (for a given directory, $DIR
):
find -L $DIR -maxdepth 1 -type l -delete
Solution 3
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
Solution 4
From man find
EXAMPLES:
find -L /usr/ports/packages -type l -exec rm -- {} +
Delete all broken symbolic links in /usr/ports/packages.
Solution 5
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
Comments
-
fotanus almost 2 years
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.
-
fotanus over 10 yearsBy you nickname, I see you like redirecting to /dev/null :-) Thanks, what about
unlink
? -
devnull over 10 years@fotanus Why
unlink
, what's the problem withrm
? -
devnull over 10 years@fotanus BTW, as mentioned, in this case redirecting to
/dev/null
was purely to avoid confusion. Even if you don't, and replaceecho
withrm
, it won't cause any sideeffect. -
fotanus over 10 yearsnot sure.. because it is a link? :P I know it only removes the entry point, but isn't somewhat safer than rm?
-
fotanus over 10 years+1 for really cool zsh example, and overall answer. But same question: Why
rm
and notunlink
? Isn't there cases whererm
is unsafe? -
fotanus over 10 yearsI don't know, I'm just asking because my tentatives used
unlink
instead. I don't know why. Maybe because it is a link? :P anyway, this is other question -
JustJeff over 9 yearswas just looking at this question: unix.stackexchange.com/questions/34248/… and the cautions regarding "find -L" -- not sure if it applies, and don't have time to chase it, but someone may want to consider investigating the potential hazards here.
-
Gilles 'SO- stop being evil' over 9 years@JustJeff The hazard mentioned there is about difficult-to-control recursion. My use of
find -L
here prevents recursion altogether, so there is no such hazard. -
thdoan over 9 yearsAnother option:
find -L /path/to/check -type l -delete
(Source: commandlinefu.com/commands/view/2369/…) -
Ohad Cohen over 8 yearsyou forgot to close the if clause in the loop option
-
Felipe Alvarez over 7 yearsI like this the best. Even the find man page seems to imply this is a solution for finding broken symlinks.
-
Diti about 7 yearsOn Mac OS (BSD
find
), @sanmiguel’s command gives an error:find: -delete: forbidden when symlinks are followed
-
personal_cloud almost 7 yearssymlinks is not preinstalled on CentOS 7.3 or Ubuntu 14. Ubuntu 16 has kernel 4.10 which has this problem: groups.google.com/forum/#!topic/linux.kernel/C1Uk5cnrPgs. Of course, if you're not running an SSL server, then Ubuntu 16 is probably fine.
-
Erdal G. over 6 yearsWorks like a charm in CentOS
-
Billy left SE for Codidact over 6 yearswhy does this find expression not use -maxdepth to prevent recursion?
-
Gilles 'SO- stop being evil' over 6 years@billycrook I don't understand. Why do you want to use
-maxdepth
? -
Billy left SE for Codidact over 6 yearsBecause "In the current directory, without recursion" is the most obvious use of -maxdepth
-
Gilles 'SO- stop being evil' over 6 years@billycrook Oh, for the first one. Because I was giving a POSIX solution and
-maxdepth
isn't in POSIX (yet, I think it's planned to be in SUSv5). -
James McGuigan about 6 years
find -L /usr/ports/packages -type l -print -delete
-
Geremia about 4 yearsYour first solution doesn't delete self-referential symlinks: "Too many levels of symbolic links."
-
Gilles 'SO- stop being evil' about 4 years@Geremia A self-referential symlink isn't broken. That solution will indeed report an error if there is a recursive symlink anywhere in the tree.
-
Geremia about 4 years@Gilles'SO-stopbeingevil' How could I delete such symlinks automatedly? thanks
-
Gilles 'SO- stop being evil' about 4 years@Geremia Please search if this has been asked already. If it hasn't, please ask a new question. It's outside the scope of this thread.
-
wheelerswebservices over 3 yearsWhat does the type -l signify here? I thought find -L was only looking at Links, but omitting the -type l flag seems to change the results.
-
sanmiguel over 3 years@JDub9 it's the difference between where to look and what to match when you look there. -L is where to look: include the contents of symlinked dirs. -type l is what to match: symlinks found when looking.
-
CherryDT over 3 yearsIt seems you misunderstood what
unlink
does. It also deletes files. Howeverunlink
, as by POSIX, is supposed to only call the syscallunlink
and not do anything else, whilerm
has more options and can do other things such as asking interactively confirming the delete. See this. -
ochitos over 3 yearswho else keeps coming back here?
-
sanmiguel over 3 years@jDub9
-L
tellsfind
to return info on the file a symlink points to, or the symlink itself if the file it points to does not exist.-type l
returns only matches that are symlinks, which immediately filters out any link targets that exist, leaving only symlinks that point to a non-existent file. -
wheelerswebservices over 3 yearsThanks @sanmiguel. That helps!
-
Sridhar Sarnobat about 3 yearsAlso available on Mac OS X:
sudo port install symlinks
-
normanius over 2 yearsCan anyone help me generalize the proposed solutions for arbitrary paths? I am not able to do this myself. The solutions are difficult to read for beginners, some more explanations would be welcome.
-
normanius over 2 yearsIs this safe and POSIX?
find -L "$DIR" -wholename "$DIR" -o -type d ...
-
Gilles 'SO- stop being evil' over 2 years@normanius
-wholename
isn't POSIX. The command is, at least, not safe if$DIR
contains wildcards. Apart from that, I don't understand what you mean by generalizing this “to arbitrary paths” since my answer doesn't use a specific path. You should ask a new question where you explain what you want to do. -
Anael over 2 yearsGreat but doesn't handle directory names with a space.