Delete all broken symbolic links with a line?

56,018

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
Share:
56,018
fotanus
Author by

fotanus

:)

Updated on July 05, 2022

Comments

  • fotanus
    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
    fotanus over 10 years
    By you nickname, I see you like redirecting to /dev/null :-) Thanks, what about unlink?
  • devnull
    devnull over 10 years
    @fotanus Why unlink, what's the problem with rm?
  • devnull
    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 replace echo with rm, it won't cause any sideeffect.
  • fotanus
    fotanus over 10 years
    not sure.. because it is a link? :P I know it only removes the entry point, but isn't somewhat safer than rm?
  • fotanus
    fotanus over 10 years
    +1 for really cool zsh example, and overall answer. But same question: Why rm and not unlink? Isn't there cases where rm is unsafe?
  • fotanus
    fotanus over 10 years
    I 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
    JustJeff over 9 years
    was 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'
    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
    thdoan over 9 years
    Another option: find -L /path/to/check -type l -delete (Source: commandlinefu.com/commands/view/2369/…)
  • Ohad Cohen
    Ohad Cohen over 8 years
    you forgot to close the if clause in the loop option
  • Felipe Alvarez
    Felipe Alvarez over 7 years
    I like this the best. Even the find man page seems to imply this is a solution for finding broken symlinks.
  • Diti
    Diti about 7 years
    On Mac OS (BSD find), @sanmiguel’s command gives an error: find: -delete: forbidden when symlinks are followed
  • personal_cloud
    personal_cloud almost 7 years
    symlinks 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.
    Erdal G. over 6 years
    Works like a charm in CentOS
  • Billy left SE for Codidact
    Billy left SE for Codidact over 6 years
    why does this find expression not use -maxdepth to prevent recursion?
  • Gilles 'SO- stop being evil'
    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
    Billy left SE for Codidact over 6 years
    Because "In the current directory, without recursion" is the most obvious use of -maxdepth
  • Gilles 'SO- stop being evil'
    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
    James McGuigan about 6 years
    find -L /usr/ports/packages -type l -print -delete
  • Geremia
    Geremia about 4 years
    Your first solution doesn't delete self-referential symlinks: "Too many levels of symbolic links."
  • Gilles 'SO- stop being evil'
    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
    Geremia about 4 years
    @Gilles'SO-stopbeingevil' How could I delete such symlinks automatedly? thanks
  • Gilles 'SO- stop being evil'
    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
    wheelerswebservices over 3 years
    What 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
    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
    CherryDT over 3 years
    It seems you misunderstood what unlink does. It also deletes files. However unlink, as by POSIX, is supposed to only call the syscall unlink and not do anything else, while rm has more options and can do other things such as asking interactively confirming the delete. See this.
  • ochitos
    ochitos over 3 years
    who else keeps coming back here?
  • sanmiguel
    sanmiguel over 3 years
    @jDub9 -L tells find 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
    wheelerswebservices over 3 years
    Thanks @sanmiguel. That helps!
  • Sridhar Sarnobat
    Sridhar Sarnobat about 3 years
    Also available on Mac OS X: sudo port install symlinks
  • normanius
    normanius over 2 years
    Can 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
    normanius over 2 years
    Is this safe and POSIX? find -L "$DIR" -wholename "$DIR" -o -type d ...
  • Gilles 'SO- stop being evil'
    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
    Anael over 2 years
    Great but doesn't handle directory names with a space.