How can I find all hardlinked files on a filesystem?

Posted on

Problem :

I need to find all hardlinked files on a given filesystem. E.g. get a list of files, each line contains linked pairs, or triplets, etc.

I understand more or less how to do it, one needs to create a dictionary keyed by inode for all files/directories on a filesystem, exclude “.” and “..” links, and then indodes with more than one name are hardlinks… But I hope that maybe a ready-made solution exists, or someone already wrote such a script.

Solution :

You can run the following command :

find / -type f -printf '%n %pn' | awk '$1 > 1{$1="";print}'

to find all hard-linked files.

Or @mbafford version:

find / -type f -links +1 -printf '%i %n %pn'

find . -type f -links +1 2>/dev/null

gives a list of all files which have more than one link, i.e. files to which there exists a hard link. Looping over this is then relatively easy – a hacky solution if you don’t have that many files would be

for i in $(find . -type f -links +1 2>/dev/null); do find -samefile $i | awk '{printf "%s ", $1}'; printf "n"; done | sort | uniq

But I sincerely hope that there are better solutions, for example by letting the first find call print inode numbers and then using find’s -inum option to show all files associated with this inode.

IMHO the best way is to use the following line (for sure you have to replace /PATH/FOR/SEARCH/ with whatever you want to search):

find /PATH/FOR/SEARCH/ -xdev -printf '%it%nt%pn' | fgrep -f <(find . -xdev -printf '%in' | sort -n | uniq -d) | sort -n

this scans the filesystem only once, shows inode, number of hardlinks and path of files with more than one hardlink and sorts them according to the inode.

if you are annoyed by error messages for folders you aren’t allowed to read, you can expand the line to this:

find /PATH/FOR/SEARCH/ -xdev -printf '%it%nt%pn' 2> /dev/null | fgrep -f <(find . -xdev -printf '%in' 2> /dev/null | sort -n | uniq -d) | sort -n

Leave a Reply

Your email address will not be published. Required fields are marked *