40

With the command:

ls -la *

I can list all my symbolic links.

How can I remove all symbolic links which are linked to a special folder?

For example:

In my directory usr/local/bin I have the following entries:

lrwxrwxrwx 1 root root 50 Apr 22 14:52 allneeded -> /usr/local/texlive/2011/bin/x86_64-linux/allneeded
lrwxrwxrwx 1 root root 47 Apr 22 14:52 amstex -> /usr/local/texlive/2011/bin/x86_64-linux/amstex
lrwxrwxrwx 1 root root 24 Apr 23 19:09 arara -> /home/marco/.arara/arara

Now I want to remove all links with the path /usr/local/texlive/

  • 1
    Do you mean remove all symlinks linked to a target folder? Or move all found symlinks into a specific folder? – George M May 25 '12 at 13:12
  • @uther: I mean removing the links. – Marco Daniel May 25 '12 at 13:18
57

Please make sure to read the alternative answer. It's even more to the point although not voted as high at this point.

You can use this to delete all symbolic links:

find -type l -delete

with modern find versions.

On older find versions it may have to be:

find -type l -exec rm {} \;
# or
find -type l -exec unlink {} \;

To limit to a certain link target, assuming none of the paths contain any newline character:

 find -type l | while IFS= read -r lnkname; do if [ "$(readlink '$lnkname')" == "/your/exact/path" ]; then rm -- "$lnkname"; fi; done

or nicely formatted

 find -type l |
 while IFS= read -r lnkname;
 do
   if [ "$(readlink '$lnkname')" = "/your/exact/path" ];
   then
     rm -- "$lnkname"
   fi
 done

The if could of course also include a more complex condition such as matching a pattern with grep.


Tailored to your case:

find -type l | while IFS= read -r lnk; do if (readlink "$lnk" | grep -q '^/usr/local/texlive/'); then rm "$lnk"; fi; done

or nicely formatted:

find -type l | while IFS= read -r lnk
do
  if readlink "$lnk" | grep -q '^/usr/local/texlive/'
  then
    rm "$lnk"
  fi
done
  • Does this command remove all symlinks? Please see my edit above.. – Marco Daniel May 25 '12 at 13:29
  • @Marco: yes, the first three lines would. Editing more :) – 0xC0000022L May 25 '12 at 13:30
  • I would also add a -print at the end of the find command to get some visual feedback. – runlevel0 Dec 14 '16 at 15:36
27

With a modern find that supports -lname:

find /usr/local/bin -lname '/usr/local/texlive/*' -delete

should do it.

  • 1
    That is a great and simple solution. I tested and it works like a charm. Thanks – Marco Daniel May 25 '12 at 15:53
  • Presumably that should be find /usr/local/bin – James Youngman May 25 '12 at 22:39
  • 1
    Not even modern, necessarily. GNU find has had -lname for longer than I have maintained it (since around 2003). – James Youngman May 25 '12 at 22:43
  • @JamesYoungman: Thanks! By modern find i really meant GNU find. ;) I used usr/local/bin, because that's what the OP used. – Christoffer Hammarström May 25 '12 at 22:52
5

The find solution is great.

Just in case your find doesn't support -lname, here's another way that uses only shell and readlink.

cd /usr/local/bin
for f in *; do
  case "$(readlink "$f")" in /usr/local/texlive/*)
    rm "$f"
    ;;
  esac
done
1

With zsh:

rm -f /usr/local/bin(@e'{[[ $REPLY:P = /usr/local/texlive/* ]]}')

$REPLY:P fully resolves the path to a symlink-free one, so assuming /usr/local/texlive is symlink free itself, it would remove all files which after symlink resolution live under /usr/local/textlive which would include links to /usr/local/texlive/foo but also to ../texlive/bar or to /usr/./local/texlive/whatever or to /some/other/symlink which is itself a symlink pointing in /usr/local/texlive, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.