Certified Supplier


We're an ISO27001:2013 Certified Supplier


File links are an integral part of the Linux filesystem, and a good understanding of them is essential if we are to manage our Linux systems effectively. It seems that most people sort of know what they are, but few understand them in detail.

Hard and Soft

There are two types of links, “hard” and “soft” (or “symbolic”). A hard link points to an inode, which in turn describes a filesystem object such as a file or a directory. A long directory listing will show how many hard links each entry has:

$ ls -l /etc |head -5
total 1812
drwxr-xr-x 3 root root 4096 Jul 13 10:04 acpi
-rw-r--r-- 1 root root 2981 Mar 20 2013 adduser.conf
-rw-r--r-- 1 root root 44 Jan 12 2015 adjtime
-rw-r--r-- 1 root root 458 Oct 28 2016 aliases

The number after the permissions mask is the number of hard links to that inode. For the regular files in the examples above, that’s 1 – the name on the line is the link to the file.

For the acpi directory, though, it’s 3, which implies that there are three names pointing to that entry. One of them is the name on the line, and looking inside the acpi directory tells us what the other two are:

$ ls -la /etc/acpi
total 24
drwxr-xr-x 3 root root 4096 Jul 13 10:04 .
drwxr-xr-x 195 root root 12288 Aug 3 00:54 ..
drwxr-xr-x 2 root root 4096 Jul 13 10:04 events
-rwxr-xr-x 1 root root 1191 Oct 23 2014

The first additional name is the . directory, which points to itself (acpi), and the second extra name is the .. directory inside events, which points to its parent (acpi). So, the three names that point to the acpi entry are:


We can see from that example that the number of links to most directories will be 2 plus the number of subdirectories within that directory.

Creating Hard Links

We can create additional hard links to regular files with the ln command. It may be easier to remember the syntax of the command by comparing it to the copy (cp) command, which has the format:

cp <from> <to>

Similarly, the syntax for the ln command is:

ln <from> <to>

Here’s a directory with one file:

$ ls -l
total 4
-rw-r--r-- 1 kae kae 211 Aug 3 08:34 myfile

We can create a new link to the file with ln:

$ ln myfile mynewlink
$ ls -l
total 8
-rw-r--r-- 2 kae kae 211 Aug 3 08:34 myfile
-rw-r--r-- 2 kae kae 211 Aug 3 08:34 mynewlink

This isn’t two files: it’s two names that point to the same file, and we can see that each entry has two links. If we display the inode numbers that each name points to, it becomes apparent that there is only one file:

$ ls -i1
37861771 myfile
37861771 mynewlink

Removing a link

The rm command, strictly speaking, doesn’t delete files: rather, it removes a link to a file. Let’s remove one of the links:

$ rm myfile 
$ ls -l
total 4
-rw-r--r-- 1 kae kae 211 Aug 3 08:34 mynewlink

The link count has decremented to one, but the file itself is unchanged. If we were to rm mynewlink, the remaining link would be removed, the link count would become zero, and the filesystem would reclaim the space used by the file.

The file itself – the data – would still exist, but be unreferenced by any directory entry. The space that the data occupies would be available for use by another file and, in the fullness of time, would be overwritten. That’s why simply using rm on a file with sensitive data isn’t secure.

Hard Link Restrictions

The filesystem is very particular about hard links to directory names because it would be easy to set up directory loops that are hard to parse. For that reason, it’s difficult to set up additional hard links to a directory:

$ mkdir mydir
$ ln mydir dirlink
ln: mydir: hard link not allowed for directory

Hard links to files are only possible within the same disk partition because the hard link is a pointer to the inode, and inode numbers are only unique within a partition:

$ ln /etc/hosts mylink 
ln: failed to create hard link 'mylink' => '/etc/hosts': Invalid cross-device link

Symbolic Links

Symbolic links, soft links or symlinks are all names for the same thing. A symlink is a pointer to another filename entry, as opposed to a pointer to the inode (file) itself. We can create a symlink with ln -s:

$ ls -l
total 4
-rw-r--r-- 1 kae kae 211 Aug 3 08:34 mydata
drwxr-xr-x 2 kae kae 40 Aug 3 08:44 mydir
$ ln -s mydata mysymlink
$ ls -l
total 4
-rw-r--r-- 1 kae kae 211 Aug 3 08:34 mydata
drwxr-xr-x 2 kae kae 40 Aug 3 08:44 mydir
lrwxrwxrwx 1 kae kae 6 Aug 3 08:52 mysymlink -> mydata

Here we can clearly see that mysymlink points to a file name, and the leading l in the permissions shows that this is a (symbolic) link. In truth, all directory entries are links, and the symbolic links are distinguished from hard links by that leading l.

We can see that the symlink doesn’t directly reference the file by looking at the inode numbers:

$ ls -li
total 4
37861771 -rw-r--r-- 1 kae kae 211 Aug 3 08:34 mydata
37875969 drwxr-xr-x 2 kae kae 40 Aug 3 08:44 mydir
37888876 lrwxrwxrwx 1 kae kae 6 Aug 3 08:52 mysymlink -> mydata

Here, the symlink inode number (37888876) differs from the filename it points to (37861771), showing that the symlink is a file in its own right.

Unlike hard links, a symlink can point to a directory or a file (or directory) on another partition:

$ ln -s mydir link-to-mydir
$ ls -l
total 4
lrwxrwxrwx 1 kae kae 5 Aug 3 08:56 link-to-mydir -> mydir
-rw-r--r-- 1 kae kae 211 Aug 3 08:34 mydata
drwxr-xr-x 2 kae kae 40 Aug 3 08:44 mydir
lrwxrwxrwx 1 kae kae 6 Aug 3 08:52 mysymlink -> mydata

Symlinks In Real Life

Most applications will follow symlinks without complaint, so if your application expects its configuration file to be called /usr/lib/myapp/myapp.conf but you want to keep your configuration file under /etc/myapp, we can do this:

$ mv /usr/lib/myapp/myapp.conf /etc/myapp/myapp.conf
$ ln -s /etc/myapp/myapp.conf /usr/lib/myapp/myapp.conf

Your application will try to open /usr/lib/myapp/myapp.conf, follow the symlink to /etc/myapp/myapp.conf, and open it seamlessly.

There’s a shortcut we can use when creating a symlink that has the same name as the real file (but in a different directory, of course). In the above example, we could do this:

$ cd /usr/lib/myapp
$ mv myapp.conf /etc/myapp
$ ln -s /etc/myapp/myapp.conf

In the ln -s command above, we haven’t specified the name or location of the symlink, so by default it is created in the current directory with the same name as the real file:

$ ln -s /etc/hosts
$ ls -l
total 0
lrwxrwxrwx 1 kae kae 10 Aug 3 09:05 hosts -> /etc/hosts

Could this Linux Tip Be Improved?

Let us know in the comments below.

Leave a Reply

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