Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

In Linux, what is the best way to find all symbolic links that point to a given file (regardless of whether the symlink is relative or absolute)? I realize this will require scanning the whole filesystem.

share|improve this question

marked as duplicate by Gilles files Jun 14 at 21:18

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

up vote 6 down vote accepted

GNU find has the -samefile test. According to the man page:

-samefile name
    File refers to the same inode as name. When -L is in 
    effect, this can include symbolic links.
$ find -L / -samefile /path/to/file

This will find all links to /path/to/file, which includes hard links and the file itself. If you only want symlinks, you can individually test the results of find (test -L).

You should read up on what the effects of -L are and ensure that it won't cause you any problems with your search.

Note: While the documentation says it looks for files with the same inode number, it does appear to work across filesystems.

e.g. /home and /tmp are separate filesystems

$ touch ~/testfile
$ ln -s ~/testfile /tmp/foo
$ ln -s /tmp/foo /tmp/bar
$ mkdir /tmp/x
$ ln -s ~/testfile /tmp/x/baz
$ find -L /tmp -samefile ~/testfile
/tmp/bar
/tmp/foo
/tmp/x/baz

Note how this is returning /tmp/bar, which is a symlink to /tmp/foo, which is a symlink to ~/testfile. If you only wanted to find direct symlinks to your target file, this wont work.

share|improve this answer

Perhaps the shortest way would be:

target="/usr/bin/firefox"    # change me
dir="/usr/bin"               # change me
realtarget="$(realpath "$target")"
for file in $(find "$dir" -print); do
    realfile="$(realpath "$file")"
    test "$realfile" = "$realtarget" && echo "$file"
done

But it's not very efficient.

If you don't have realpath, install it, e.g. apt-get install realpath. You could also use stat -N or ls -l or pwd -P to emulate realpath, but those ways are harder.

Also, the above example won't handle file names with spaces in it properly. Here's a better way to do it. Note that IFS=$'\n' requires bash or zsh.

OIFS="$IFS"
IFS=$'\n'
target="/usr/bin/firefox"    # change me
dir="/usr/bin"               # change me
realtarget="$(realpath "$target")"
find "$dir" -print | while read -r file; do
    realfile="$(realpath "$file")"
    test "$realfile" = "$realtarget" && echo "$file"
done
IFS="$OIFS"
share|improve this answer

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