How to effectively trace hardlink in Linux?
First, there is no original file in the case of hard links; all hard links are equal.
However, hard links aren’t involved here, as indicated by the link count of 1 in ls -l
’s output:
$ ll -i /usr/bin/bash /bin/bash 1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /bin/bash* 1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /usr/bin/bash*
Your problem arises because of a symlink, the bin
symlink which points to usr/bin
. To find all the paths in which bash
is available, you need to tell find
to follow symlinks, using the -L
option:
$ find -L / -xdev -samefile /usr/bin/bash 2>/dev/null
/usr/bin/rbash
/usr/bin/bash
/bin/rbash
/bin/bash
I’m using -xdev
here because I know your system is installed on a single file system; this avoids descending into /dev
, /proc
, /run
, /sys
etc.
how do I trace the original file or every hardlink using /usr/bin/bash file as reference
With GNU find (or any other version of find
that has the -samefile
option), and assuming that /usr/bin/bash
is located on the /
filesystem, this is correct:
find / -xdev -samefile /bin/bash
Use -xdev
since hard links can't cross filesystem boundaries. Do not redirect errors: if you don't have permission to traverse a directory, a hard link could be present under that directory and you'd miss it.
The mistake you're making is that you're looking for another hard link that doesn't exist. You actually have the information to know that it doesn't exist:
1310813 -rwxr-xr-x 1 root root 1183448 Jun 18 21:14 /bin/bash*
^
The hard link count of /bin/bash
is 1.
There is a single file in /
which is the same as /usr/bin/bash
. The file /bin/bash
is the same as /usr/bin/bash
for a different reason: the directories /bin
and /usr/bin
are the same file. Since find / -samefile /bin/bash
points to /usr/bin/bash
, /bin
has a symbolic link to /usr/bin
. More precisely, from the information in the question, and assuming that /bin
is not a directory hard link (a poorly supported, rarely used feature), we know that /bin
is a symbolic link which resolves to /usr/bin
; it could be a symbolic link to another symbolic link and so on eventually resolving to /usr/bin
or to some equivalent path such as ///////usr/bin/
, but most likely it's a symbolic link whose target is /usr/bin
.
Looking for all symbolic links to a file on the whole system is not particularly productive. For example, on Linux, there's a file /proc/*/exe
which is a symbolic link to /usr/bin/bash
(or /bin/bash
) for every process that's running bash. And if you look for symbolic links to a directory, you'll end up inside infinite recursion, for example with /proc/*/root
pointing to /
(except for chrooted processes).
If you need to know whether two paths point to the same file, on Linux, you can use either of
[ /bin/bash -ef /usr/bin/bash ]
test /bin/bash -ef /usr/bin/bash
(-ef
isn't POSIX but it's in dash, bash, BusyBox and GNU coreutils). If you need to get a canonical path to a file, in the sense that distinct files always have distinct canonical names, you can use
readlink -f /bin/bash
(This can miss files that are equal via mounted directories, for example if the same network location is mounted in two different ways.)