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.

3 Answers 3


You can run the following command :

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

to find all hard-linked files.

Or @mbafford version:

find / -type f -links +1 -printf '%i %n %p\n'
  • 1
    Thanks, this is not exactly what I wanted, but close enough. I can add '%i' to print the inode numbers and then sort/group by it...
    – haimg
    Oct 10, 2012 at 15:59
  • 24
    You can avoid the need for awk by using find's "-links +n' syntax. e.g. to find all files with at least two links and print out the necessary info: find / -type f -links +1 -printf '%i %n %p\n'
    – mbafford
    Jan 16, 2015 at 14:50
  • how about piping through sort (+ uniq)? i was curious so gave it a go on my main computer (16GB i5-2500k with ssd). with 2187757 files (find / -xdev -type f | wc) takes 12 real secs when returning 3820 files / 570 inodes (time sudo find / -xdev -type f -links +1 -printf "%i\n" | sort | uniq | wc). you would need to include the %n %p for the actual files as i took them out for counting inodes. Oct 24, 2018 at 9:45
  • This was close to what I needed.... I wanted to find all files that were not hard linked. That can be done by changing the "+1" to just "1". I.e. find / -type f -links 1 -printf '%i %n %p\n'
    – Alan
    Feb 26, 2021 at 12:05
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.

  • 1
    Ouch! This scans the filesystem again and again for each hardlinked file...
    – haimg
    Oct 10, 2012 at 16:01
  • 1
    I didn’t claim it was fast – and it sort-of-works for small directory trees. Of course, a proper index, that could be built from, for example, the output of find . -type f -printf '%i %p\n', would allow one to build a much faster solution.
    – Claudius
    Oct 10, 2012 at 16:08
  • And that don't handle space in path AFAIK. Oct 10, 2012 at 16:12
  • For the for loop, adjusting IFS accordingly would work. To parse the output of the find command in my comment, declaring everything between the first space and the end of the line to be the filename should work, too.
    – Claudius
    Oct 10, 2012 at 16:13
  • 1
    @Sati: it ensures that error messages are discarded (e.g. for folders you haven't access to like lost+found etc.); which is especially important, if the output should be processed further like in the second line. Oct 1, 2018 at 18:40

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 '%i\t%n\t%p\n' | fgrep -f <(find . -xdev -printf '%i\n' | 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 '%i\t%n\t%p\n' 2> /dev/null | fgrep -f <(find . -xdev -printf '%i\n' 2> /dev/null | sort -n | uniq -d) | sort -n
  • You have find . nested within the <(...). What is the expected working directory for this oneliner? May 28, 2020 at 17:49

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.