Hard Links – Do They Count as Normal Files?

bashfileshard linkshell-script

I was wondering if there was a way to register this, but since most modern search engines don't work well with phrases over about 5 words in length, I need some help on this one.

I was wondering this because I'm making a bash script that has to register files as certain types and make decisions accordingly. This technically isn't important to my project, but I was curious.

Also, if they are considered to be regular files, then is there a way to check if these files are hard linked without having to parse ls -i? And is there a way to check if some arbitrary file, X, is hard linked to some other arbitrary file, Y, without using the find -i command?

Best Answer

In Unix-style systems, the data structure which represents filesystem objects (in other words, the data about a file), is stored in what's called an "inode".

A file name is just a link to this inode, and is referred to as a "hard link". There is no difference between the first name a file is given and any subsequent link. So the answer is, "yes": a hard link is a regular file and, indeed, a regular file is a hard link.

The ls command will show you how many hard links there are to the file.

For example:

seumasmac@comp:~$ echo Hello > /tmp/hello.txt
seumasmac@comp:~$ ls -l /tmp/hello.txt 
-rw-rw-r-- 1 seumasmac seumasmac 6 Oct  4 13:05 /tmp/hello.txt

Here we've created a file called /tmp/hello.txt. The 1 in the output from ls -l indicates that there is 1 hard link to this file. This hard link is the filename itself /tmp/hello.txt.

If we now create another hard link to this file:

seumasmac@comp:~$ ln /tmp/hello.txt /tmp/helloagain.txt
seumasmac@comp:~$ ls -l /tmp/hello*
-rw-rw-r-- 2 seumasmac seumasmac 6 Oct  4 13:05 /tmp/helloagain.txt
-rw-rw-r-- 2 seumasmac seumasmac 6 Oct  4 13:05 /tmp/hello.txt

you can now see that both filenames indicate there are 2 hard links to the file. Neither of these is the "proper" filename, they're both equally valid. We can see that they both point to the same inode (in this case, 5374043):

seumasmac@comp:~$ ls -i /tmp/hello*
5374043 /tmp/helloagain.txt  5374043 /tmp/hello.txt

There is a common misconception that this is different for directories. I've heard people say that the number of links returned by ls for a directory is the number of subdirectories, including . and .. which is incorrect. Or, at least, while it will give you the correct number, it's right for the wrong reasons!

If we create a directory and do a ls -ld we get:

seumasmac@comp:~$ mkdir /tmp/testdir
seumasmac@comp:~$ ls -ld /tmp/testdir
drwxrwxr-x 2 seumasmac seumasmac 4096 Oct  4 13:20 /tmp/testdir

This shows there are 2 hard links to this directory. These are:

/tmp/testdir
/tmp/testdir/.

Note that /tmp/testdir/.. is not a link to this directory, it's a link to /tmp. And this tells you why the "number of subdirectories" thing works. When we create a new subdirectory:

seumasmac@comp:~$ mkdir /tmp/testdir/dir2
seumasmac@comp:~$ ls -ld /tmp/testdir
drwxrwxr-x 3 seumasmac seumasmac 4096 Oct  4 13:24 /tmp/testdir

you can now see there are 3 hard links to /tmp/testdir directory. These are:

/tmp/testdir
/tmp/testdir/.
/tmp/testdir/dir2/..

So every new sub-directory will increase the link count by one, because of the .. entry it contains.

Related Question