7

Softlinks are easily traceable to the original file with readlink etc... but I am having a hard time tracing hardlinks to the original file.

$ 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*
                   ^

above is as expected - cool --> both files point to same inode 1310813
(but the number of links, indicated by ^, shows to be 1. From Gilles answer the reason for this can be understood)

$ find / -samefile /bin/bash 2>/dev/null
/usr/bin/bash

above is as expected - so no problems.

$ find / -samefile /usr/bin/bash 2>/dev/null
/usr/bin/bash  

above is NOT cool. How do I trace the original file or every hardlink using the /usr/bin/bash file as reference?

Strange - below did not help either.

$ find / -inum 1310813 2>/dev/null
/usr/bin/bash
  • 9
    File system designs tend to make it simple to map a path to an inode; that's the primary purpose of a file system. The other direction, though, typically isn't tracked. The only real way to find all paths that map to a given inode is to check all candidate paths. – chepner Sep 3 at 13:29
  • 2
    As noted elsewhere, you don't actually have a hardlink here. Assuming you have GNU readlink (which you should on Linux, but not necessarily on other *nix platforms), note that readlink -f will fully canonicalize a path... which, in this instance, would reveal that the canonical path of /bin/bash is indeed /usr/bin/bash. – Matthew Sep 3 at 15:30
  • @Matthew but that doesn’t help with the problem the OP is ultimately trying to solve, finding the package which owns /usr/bin/bash (which is installed as /bin/bash). The canonical location from readlink’s perspective doesn’t match the canonical location from the package manager’s perspective. That’s why the OP is looking for links to /usr/bin/bash, not what /bin/bash links to. – Stephen Kitt Sep 4 at 4:49
  • @StephenKitt, that sounds like a package manager problem. rpm identifies bash-5.0.17-1.fc32.x86_64 as the owner of both /bin/bash and /usr/bin/bash. Anyway, I don't see that information in the question, so expecting me to be aware of it isn't very reasonable. – Matthew Sep 4 at 12:41
  • 1
    Does this answer your question? What happens when you copy a hardlink? – cg909 Sep 4 at 14:57
44

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.

| improve this answer | |
  • 3
    There is no additional hard link here. – Michael Hampton Sep 3 at 2:28
  • 3
    As far as I can tell my answer doesn’t say it’s a hard link. The OP is looking for the paths at which a given binary is installed (see this question for context); because of the /usr merge, bash is installed as /bin/bash but also shows up as /usr/bin/bash. – Stephen Kitt Sep 3 at 4:57
  • 2
    Worth pointing out that you can tell there's no hardlink because the link-count is 1. That's how you know it must be something else. – Peter Cordes Sep 4 at 14:07
24

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.)

| improve this answer | |
  • @gilles-so-stop-being-evil, @Stephen-Kitt, - less related Q, but The hard link count of /bin/bash is 1., what does ls -l third column mean for dirs. If I got it right, it means the number of dir entries within the listed dir. So is not that quite different for files and directories – samshers Sep 3 at 12:30
  • 1

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.