Hard Link Vs Symbolic Link 101
Tags: hardlink, symboliclink, softlink, linux
Published: 2021-08-25 13:03:17

---
title: Hard Link Vs Symbolic Link 101
published: true
description: Hard Link Vs Symbolic Link 101
tags: hardLink, symbolicLink, softLink, linux
//cover_image: https://direct_url_to_image.jpg
---

You probably have heard of "hard link" (`ln`) and "symbolic link" (`ln -s`). You may have some vague idea that these commands have something to do with linking a file to another file... or something like that. This article will clarify the differences between `ln` and `ln -s` and provide some use cases.

To get the most out of this, I strongly encourage you to code along as you read. Meaningful reading is not passive. It is an active act where you, the reader, must also put in the work to get the most out of this article. 

As much as you can, do lots of experiments on your own: try different variations of a command, repeat the command without looking at the article, and repeat it again the next day to fortify your memory (you'll be surprised at how fast you forget things!).

# Hard Link

If you have Googled "hard vs soft link" in the past, you might have seen a reference to an "inode". An inode is a file's unique serial number. When you create a new file (`touch newfile.txt`), you are actually creating an inode and a link to that inode. That file that you just created consists of at least two parts: an inode (a unique identifier) and a file name.

Let's create a file, `test1.txt`. Inside it, add some texts:

```
touch 'hello test1' >> test1.txt
```

Aight, you created a file. Now let's create a hard link - let's call it `hard1.txt`. Remember - when you create a new hard link, you are creating a new link to the inode of the original file.

```
ln test1.txt hard1.txt
```

Now run `ls -l`. You should see two files displayed: a `test1.txt` and a `hard1.txt`. If you run `cat hard1.txt`, you'll see that it has the same content as `test1.txt`.

Next, add a line into `test1.txt`:

```
echo "Hello again test1" >> test1.txt
```

You'll see "Hello again test1" inside *both* `test1.txt` and `hard1.txt`. Changing the original file changes the hard link file as well!

What if we change the content of `hard1.txt` instead? Let's find out!

```
echo "Hello from hard1" >> hard1.txt
```

You should see "Hello from hard1" text inside both `hard1.txt` and `text1.txt`. So changing *either* the original or the hard link file changes the other.

Finally, let's see what happens if we delete the original file, `test1.txt`.

```
rm test1.txt
```

Notice that `hard1.txt` is still there and the text inside hasn't changed. Great!

Let's recap. When you created `test1.txt`, you created an inode. It contained "hello test1" initially. This inode (I'll call it "test1 inode") is connected to a file name `test1.txt`. When you ran `ln test1.txt hard1.txt`, you created a new file name, `hard1.txt`, connected to the test1 inode. Think of test1 inode like an underground rabbit's burrow. `test1.txt` and `hard1.txt` are the two holes connecting that burrow to the surface. From the outside, we see two holes. If you remove one hole, the bunny can still go out from the other hole. If you create a new hard link, you are just creating a third hole to the same, existing burrow. If you delete the `test1.txt` burrow, it won't affect `hard1.txt` at all! The only way to remove it is to completely remove all references to the inode. You need to remove all the hard links.

A few things that I'd like you to do:
1. We've deleted `test1.txt` but we still have `hard1.txt`. Create another hard link out of `hard1.txt`, name it `anotherhard1.txt`. What do you expect to happen? What does this tell you about the `rm` command? *(It doesn't really "delete" the file. It actually deletes a link to an inode)*
2. Rename `hard1.txt` to another name, `hardy1.txt`. What is the relationship between `anotherhard1.txt` and `hardy1.txt`?
3. Modify the content of one of the hard links. What do you think will happen to the content of the rest of the links?
4. When do you think a hard link might come in handy? What is the use case?
5. By the way, if you want to see the inode of a file, you can use `ls -i hard1.txt`. Compare the inode number of a file vs its hard link and the inode number of a file vs its symlink (do this one later after you read the symlink section). You will find that the hard link has the same inode number as the original link and that a symlink has a different inode number as the original link. 

Don't go to the next section yet. Spend some time creating your own hard links. Modify them. Do things that weren't covered in this section.

## Symbolic / Soft link

Unlike a hard link that points a file to an inode, a symbolic link (sometimes known as a soft link) connects by a file name, not an inode. Because it doesn't connect to an inode like that underground rabbit burrow analogy and it only connects on the surface level, their connection is "softer / weaker" than hard links (that's how I think about it anyway). As a result, by simply changing the name of the original file, you destroy its connection.

Create a new file `test2.txt` and add a line into it:

```
echo "hello test2" >> test2.txt
```

Now create a symlink:

```
ln -s test2.txt soft2.txt
```

If you check the content inside `test2.txt` and `soft2.txt`, you'll notice that they are one and the same. Good.

Let's update the content:

```
echo "hello soft2" >> soft2.txt
cat soft2.txt
cat test2.txt

echo "hello original" >> test2.txt
cat soft2.txt
cat test2.txt
```

Notice that updating *either* the symlink file or the original file updates the other file. So far symlink acts like a hard link.

Now here comes the kicker. If you either *change the name* of the original file or *remove the original file* (`rm test2.txt`), it will break the connection.

```
rm test2.txt

cat soft2.txt
cat: soft2.txt: No such file or directory
```

Retrospectively, if you had renamed the original file:

```
mv test2.txt somethingelse2.txt

cat soft2.txt
cat: soft2.txt: No such file or directory
```

However, if you instead had removed the symlink file instead and kept the original file, the content of the original file is preserved.

```
rm soft2.txt

cat test2.txt
# content is still there
```

Spend some time to play around with symlinks. Do the things that I didn't mention in this section. Learn by breaking things.

Here are some things to think about:
1. Can you create a soft link out of a soft link?
2. What would happen if you move the location of the original file to a different directory (but keep the same name)?
3. Can you create a soft link out of a hard link?
4. Can you create a hard link out of a soft link?
5. Create a symlink *and* a hard link from a file. Do different things to each. Notice how they differ.

# Usage

Now that you know what the differences between `ln` and `ln -s` are, let's talk about usage.

One usage for a symbolic link is to create portable dotfiles. I use Vim as a text editor. Vim can be configured with a `.vimrc` file and a `.vim/` directory in the root directory. But what if I want to keep my dotfiles portable and my config files source-of-truth inside `~/Projects/iggy-dotfiles/vimrc` and `~/Projects/iggy-dotfiles/vim/`?

Before learning about `ln`, I used to copy-paste the `vimrc` file and `vim/` directory from my dotfiles into the root directory. But if I copy-paste them, anytime I make changes to `~/.vimrc`, I would have to apply the same change to my `~/Projects/iggy-dotfiles/vimrc` file (I can also use `rsync`, but that still requires a manual syncing). That's not good. I want to change either `~/.vimrc` or `~/Projects/iggy-dotfiles/vimrc` and have the other file to update automatically - wait a second... this sounds like symlink! 

A better way is to run:

```
rm ~/.vimrc
ln -s ~/Projects/iggy-dotfiles/vimrc ~/.vimrc
```

With this, each time I make changes to *either* dotfiles vimrc or root vimrc, the content will always be the same. Btw, you can also use a symlink on a directory, so `ln -s ~/Projects/iggy-dotfiles/vim/ ~/.vim` should work.

By the way, you could've also used a hard link, but the popular convention is to use symlink. If I ever need to delete a file, I can just delete `~/Projects/iggy-dotfiles/vimrc` and my `~/.vimrc` will automatically become obsolete. Having only one source of truth makes it easier to keep track of where things are. If you used a hard link, you'll have to remember to delete all of your vimrc sources.

You can use this technique with any config files like `.zshrc`, `.bashrc`, `.launch.json`, etc.

On the other hand, hard links are useful for backups. For example, if you have a directory full of books:

```
aesop_fables.pdf
bradbury_fahrenheit.pdf
calvin_institutes.pdf
darwin_origin.pdf
...
```

Assume that you need to create multiple directories so you can sort them based on author and title. It doesn't make sense to copy all your books into the directory `authors/` and once more in `title/`. It makes more sense if you keep the original books, then create a hard link twice (remember, creating a hard link *barely takes up any space*). Inside the `authors/` directory you can have your books named and sorted by author. Inside the `title/` directory you can name and sort them by title. You can "duplicate" and "sort" your data as many ways as you want and they will barely take up any space.

We've reached the end. Thanks for making it this far. Hopefully by now you've understood `ln` vs `ln -s` and put this knowledge to good use. Keep learning and happy coding!