25

On this question or on this one (for example) you will get solutions on how to look for symlinks pointing to a given directory (let's call it /dir1), while I am interested to symbolic links possibly pointing to any file/folder inside /dir1.

I want to delete such directory but I am not sure that I am safe to do so, as on an other directory (let's call it /dir2), I may have symlinks pointing to inner parts of /dir1.

Further, I may have created these symlinks using absolute or relative paths. My only help is that I know the symlinks I want to check are on a mounted filesystem, on /dir2.

20

You can find all the symbolic links using:

find / -type l 

you might want to run this as root in order to get to every place on the disc.

You can expand these using readlink -f to get the full path of the link and you should be able to grep the output against the target directory that you are considering for deletion:

find / -type l -exec readlink -f {} + | grep -F /dir2

Using find / -type l -printf '%l\n' doesn't work as you get relative links like ../tmp/xyz which might be pointing to your target dir, but are not matched because they are not fully expanded.

3
  • 2
    In case of subtree it can be useful to follow symlinks: find -L /subtree -xtype l -exec readlink -f {} + – ruvim Nov 30 '17 at 11:52
  • What does the + do here? – Liam Jul 21 '20 at 15:24
  • 1
    @Liam It tells find that the -exec is finished and that multiple arguments should be passed to the command (readlink) at the position of {} (you can also finish with ; (which needs to be escaped in many shells), to invoke the command with a single argument, which is much slower to execute. – Anthon Jul 21 '20 at 20:03
13

In my case, the accepted answer wasn't useful (because it didn't output the link source). Here is what worked for me.

I worked around it using two -exec clauses:

find /home/ -type l -exec readlink -nf {} ';' -exec echo " -> {}" ';' | grep "/dir2"
2
  • 3
    This works, but the arrow (->) is misleading, it should point from right to left (<-). – Attila Csipak Oct 5 '20 at 13:54
  • Rather than flipping the arrow, this would print the expected output: find /home/ -type l -printf '%p -> ' -exec readlink -f {} ';' | grep "/dir2" – MichaelK Feb 23 at 20:56
1

With zsh:

printf '%s\n' /dir2/**/*(D@e'([[ $REPLY:P = /dir1(/*|) ]])')
0

Depending on your circumstances, you could delete the directory, then delete any resultant invalid symlinks with the following:

find -xtype l -delete

The xtype test returns 'l' if the symlink is broken.

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.