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!
Recommended Course 📺
👉 Learn Node, a video course by Wes Bos 👈
You'll learn things like user auth, database storage, building a REST API and uploading images in Node.js by building a real world restaurant application.
ⓘ About this affiliate link
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:
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:
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:
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 one one one
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.
Conclusion
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!