How can I tell if two files are hard-linked from the command line? e.g. something link this:
$ ls
fileA fileB fileC
$ is-hardlinked fileA fileB
yes
$ is-hardlinked fileA fileC
no
How can I tell if two files are hard-linked from the command line? e.g. something link this:
$ ls
fileA fileB fileC
$ is-hardlinked fileA fileB
yes
$ is-hardlinked fileA fileC
no
On most filesystems¹, a file is uniquely determined by its inode number, so all you need to check is whether the two files have the same inode number and are on the same filesystem.
Ash, ksh, bash and zsh have a construct that does the check for you: the file equality operator -ef
.
[ fileA -ef fileB ] && ! [ fileA -ef fileC ]
For more advanced cases, ls -i /path/to/file
lists a file's inode number. df -P /path/to/file
shows what filesystem the file is on (if two files are in the same directory, they're on the same filesystem). If your system has the stat
command, it can probably show the inode and filesystem numbers (stat
varies from system to system, check your documentation). If you want a quick glance of hard links inside a directory, try ls -i | sort
(possibly piped to awk).
¹ All native unix filesystems, and a few others such as NTFS, but possibly not exotic cases like CramFS.
function is-hardlinked() {
r=yes
[ "`stat -c '%i' $1`" != "`stat -c '%i' $2`" ] && r=no
echo $r
}
stat -c %d
). And if you're on Linux (given your stat
command), your shell has the [ fileA -ef fileB ]
to do all this directly. Also, your command gratuitously breaks with file names containing whitespace or \[?*
, or begins with -
: always put double quotes around command susbtitutions ("$(stat -c %i -- "$1")"
).
– Gilles 'SO- stop being evil'
Jan 29 '13 at 15:41
function
keyword with a function name that (on account of containing a dash) violates POSIX conventions on allowed names?
– Charles Duffy
May 19 '17 at 22:25
$1
and $2
. You might also want to use the $()
syntax instead of backticks because the brackets make it clear where the command begins and where it ends and nesting is simpler.
– josch
Dec 30 '18 at 16:08
[
's -ef
checks whether the files are the same after symlink resolution, while GNU stat
by default gets information from the symlink itself, so it's not equivalent. You can't use [
's -ef
to check that two symlink files are hard linked to each other. GNU find
's -samefile
can be used instead or approaches based on various implementations of stat
(provided you get both device and inode number as you said).
– Stéphane Chazelas
Jun 01 '22 at 11:12
As the first poster suggest, you can write a script based on something like this on Linux:
stat -c '%i' fileA fileB fileC
stat -c %d
). And if you're on Linux (given your stat
command), your shell has the [ fileA -ef fileB ]
to do all this directly.
– Gilles 'SO- stop being evil'
Jan 29 '13 at 15:42
[
's -ef
checks whether the files are the same after symlink resolution, while GNU stat
by default gets information from the symlink itself, so it's not equivalent. You can't use [
's -ef
to check that two symlink files are hard linked to each other. GNU find
's -samefile
can be used instead or approaches based on various implementations of stat
(provided you get both device and inode number as you said).
– Stéphane Chazelas
Jun 01 '22 at 11:11
With GNU find(1)
version 4.2.11 or newer you can also use this:
if [ yes = "$(find fileA -prune -samefile fileB -printf yes)" ]; then
echo yes
else
echo no
fi
If fileA
is the same file as fileB
then find
will print "yes" and the condition becomes true.
In contrast to using the file equality operator -ef
this will spawn a new process.
You can do this very simply with the built-in bash operator -ef
:
[[ file1 -ef file2 ]] && echo Same
If the condition evaluates to true (file1
and file2
are the same), then it prints "Same". Otherwise, nothing is output.
file1
is a symbolic link to file2
, or the other way around. I don't really see a difference between this and the accepted answer (which has the same issue).
– Kusalananda
Jan 09 '21 at 23:13
theres is other solution in the sh
shell :
#!/bin/sh
file1='readlink $1'
file2='readlink $2'
if [ file1==file2 -o file2==file1 ]
then
echo "the files are linked with strong link"
else
echo "the files are not linked"
fi
the readlink
give us the right to copy the inode
into a string variable and compare it with other string variable . (two files have a string link have the same inode
).
readlink
, will not expand $1
nor $2
, and will treat file1==file2
as one string, and file2==file1
as another, and both are always true (as they are non-empty strings). Additionally, readlink
deals with symbolic links, not hard links.
– Kusalananda
Jun 01 '22 at 11:13
fileA -ef fileB
also returns0
(success) iffileA
is a symlink tofileB
, or vice versa, or they both link to the same file. – janmoesen Nov 08 '11 at 16:50[ .bashrc -ef .bash/.bashrc ]
is correct. Without context, of course, I have no idea why it “didn't really work” — you could be comparing the wrong files, you could be not checking the outcome correctly, you could be using a shell without-ef
, ... – Gilles 'SO- stop being evil' Jun 15 '14 at 10:49[
and is a synonym oftest
. Butman [
orman test
will give you the man page of the external command, whereas just about every shell out there has a built-in command with slightly different options, so you need to look this one up in your shell's manual. – Gilles 'SO- stop being evil' Jun 15 '14 at 18:33if [ fileA -ef fileB]; then echo Yes; else echo No; fi
– palswim May 09 '17 at 18:53