Command-line Basics: Symbolic Links

While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

Symbolic links allow you to links files and directories to other files and directories. They go by many names including symlinks, shell links, soft links, shortcuts, and aliases. At a glance, a symbolic link looks like just a file or directory, but when you interact with them, they will actually interact with the target at the other end. Think of them like worm holes for your file system.

Getting started

The system call necessary to create symbolic links tends to be readily available on Unix-like and POSIX-compliant operating systems. The command we’ll be using to create the links is the ln command.

You’re welcome to use the files on your system to mess around with, but I thought it would be nice to provide a few lines of code to setup an environment for following along with this post:

$ mkdir -p /tmp/symlinks/{one,two}
$ cd /tmp/symlinks
$ echo "one" > ./one/one.txt
$ echo "two" > ./two/two.txt

If you were to run tree, it should look like this:

$ tree
├── one
│   └── one.txt
└── two
    └── two.txt

2 directories, 2 files

Perfect, let’s get to linking!

Hard linking

By default, the ln command will make hard links instead of symbolic, or soft, links.

To ensure that we’re creating symbolic links, we’ll want to pass the -s or --symbolic argument to the ln command.

What’s a hard link anyway?

Hard links link directly to the inode where the item resides on the disk, instead of acting as a pointer to the original file, the way symbolic links do. What you end up with is a copy of the original and any changes to the original will not be reflected.

Hard links serve their purpose in the world, but should be avoided when linking inside of of a git repository as they cause a ton of confusion.

From my own experience, I’m always using symbolic links, but never hard links. As I write this, I’m wondering why I have yet to alias ln to ln -s to save a few keystrokes:

alias ls="ln -s"

Symbolic linking

As mentioned, symbolic linking is effectively like creating a file that contains the target’s filename and path.

Because it’s simply a reference to the original file, any changes that are made to the original will be immediately available via the symbolic link.

Some of my favorite uses for symbolic links are to create local directories in my home directory that point to files being synchronized by Dropbox or to link current to the latest build of a project in a directory that is dynamically named and includes a date and time.

Given the files we created earlier in the getting started section, let’s go ahead and try linking the one directory to the three directory:

$ ln -s one three

Now we should have 3 directories, one of which is pointing back to another. To see things in more detail, we can use the ls command:

$ ls
one/  three@  two/

Notice the @ symbol? That indicates that the file is a symbolic link!

For even greater detail, we can pass in the -l argument and see where the symbolic link is actually pointed:

$ ls -l
total 0
drwxr-xr-x 2 josh josh 60 Sep 13 17:18 one/
lrwxrwxrwx 1 josh josh  3 Sep 13 17:34 three -> one/
drwxr-xr-x 2 josh josh 60 Sep 13 17:18 two/

As expected, the three link is pointed to the one directory.

Symbolic links can also contain symbolic links, so we could go ahead and link the one.txt file from three to the two directory:

$ ln -s three/one.txt two/one.txt

We should now have a file named one.txt inside of the two directory. Depending on your terminal configuration, this file very well may be blinking red.

Even though the symbolic link was created, the way we specified the path was relative and thus, the link is broken because the two directory doesn’t contain a three directory with the one.txt file in it.

Fortunately, we can remedy this situation but telling ln to create the symbolic link relative to the link location using the -r or --relative argument.

Not so fast though, because the symbolic link already exists, we can’t overwrite it without passing in the -f or --force argument as well:

$ ln -srf three/one.txt two/one.txt

Great! We now have two/one.txt which was linked to three/one.txt which is a link to one/one.txt.

Phew, what a mouthful.

Funny enough, your file system thinks it’s a mouthful as well. When we run tree, the link target being shown is actually that of our original location and not to the link itself:

$ tree
├── one
│   └── one.txt
├── three -> one
└── two
    ├── one.txt -> ../one/one.txt
    └── two.txt

3 directories, 3 files

Now that things are linked up nice, we can really see how symbolic links work by messing with the file contents.

Here’s what all of our one.txt files look like right now:

$ cat {one,two,three}/one.txt

And if we were to update the contents of the original file and check again:

$ echo "1. One" > one/one.txt
$ cat {one,two,three}/one.txt
1. One
1. One
1. One

Or even if we changed the contents via one of the symbolic links:

$ echo "One and done" > three/one.txt
$ cat {one,two,three}/one.txt
One and done
One and done
One and done

Because symbolic links are simply pointers to files, any change we make, to the original file or the symbolic links will be immediately reflected in the original file or any symbolic links to the file.


I hope you enjoyed this introduction to symbolic links. I do want to leave you with one word of caution though.

While linking is pretty great, and can make your life a ton easier, keep in mind that if you were to move or delete the original file or directory, all of your existing symbolic links pointed to it will become broken. There’s no automatic updating in that scenario.

Hopefully this small short coming doesn’t scare you off from using this powerful command-line functionality!

Creative Commons License