Skip to main content

Sysadmin fundamentals: Create soft links in Linux

Symbolic links (also called "soft" links) are files that point to a file or directory in your system, but don't mirror the other file's data.

In my previous article, I demonstrated how to create a hard link that looks like a unique file but actually points back to another file. A hard link can only point to a file, not a directory, and it doesn't add to the overall index node (inode) count.

[ Keep your most commonly used commands handy with the Linux commands cheat sheet. ]

An inode is a data structure describing a filesystem object, such as a file or a directory. It stores metadata pertaining to that object, including time stamps, block maps, or extended attributes.

You can see inodes in action by creating a directory and then looking at its inode and size information:

$ mkdir dir

$ ls -li
total 0
25606589 drwxrwxr-x. 2 localuser localuser 6 set 19 15:21 dir

$ stat dir

  File: dir
  Size: 6         	Blocks: 0          IO Block: 4096   directory
Device: fd00h/64768d	Inode: 25606589    Links: 2
Access: (0775/drwxrwxr-x)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-19 15:21:27.616000000 -0300
Modify: 2022-09-19 15:21:27.616000000 -0300
Change: 2022-09-19 15:21:27.616000000 -0300
 Birth: 2022-09-19 15:21:27.616000000 -0300

Use the ls command with the -i option to display inodes. You can see that the inode address of the given dir directory below is 25606589. You can confirm the inode and check other metadata information with the stat command.

Create a file inside this directory and check the same information:

$ touch dir/file

$ stat dir

  File: dir
  Size: 18        	Blocks: 0          IO Block: 4096   directory
Device: fd00h/64768d	Inode: 25606589    Links: 2
Access: (0775/drwxrwxr-x)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-19 15:29:37.495000000 -0300
Modify: 2022-09-19 15:29:40.276000000 -0300
Change: 2022-09-19 15:29:40.276000000 -0300
 Birth: 2022-09-19 15:21:27.616000000 -0300

$ ls -li dir/file

25606591 -rw-rw-r--. 1 localuser localuser 0 set 19 15:29 dir/file

$ stat dir/file

  File: dir/file
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 25606591    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-19 15:29:40.276000000 -0300
Modify: 2022-09-19 15:29:40.276000000 -0300
Change: 2022-09-19 15:29:40.276000000 -0300
 Birth: 2022-09-19 15:29:40.276000000 -0300

The file has its own inode address (25606591), and it's 0 bytes in size because it has no contents. Add just one single byte of data to it and see what happens:

$ echo 1 > dir/file

$ stat dir/file

  File: dir/file
  Size: 2         	Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 25606591    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-19 15:29:40.276000000 -0300
Modify: 2022-09-19 15:36:18.812000000 -0300
Change: 2022-09-19 15:36:18.812000000 -0300
 Birth: 2022-09-19 15:29:40.276000000 -0300

The file now consumes eight sectors, even though you only added 1B of data. That is because you're working with the default 4KiB block disk size and 512B sector size.

The inode address remains the same, which is important because regardless of the file size, it's always referenced by its inode address, not each individual sector consumed. If you copy the file, though, the copy would get its own inode address, and it would consume another eight sectors. That's significant because you don't make a copy when you create a link.

What are symbolic links?

Unlike hard links, symbolic links (also called "soft" links) are just special files that point to a file or directory in your system. Symbolic links have advantages over hard links in some scenarios, such as creating links for directories, pointing to files or directories in another filesystem, having a different inode and permissions than the original file or directory, and having a small size. By acting as a pointer to the original content and not being a mirror of it, its size is only the number of bytes necessary to compose the name of the file or directory.

[ Learn how to manage your Linux environment for success. ]

Symbolic links have limitations, however. Because you're just creating a pointer to a directory, if you change the original directory name or location, then you "break" your pointer. Your symbolic link cannot find the file or directory it's linked to anymore unless you change the original object back to the name or location you used when you created the symbolic link. Also, symbolic links don't inherit the original permissions from the original file. That means any permission changes made in the original file aren't reflected in the symbolic link.

Create soft links

To create a symbolic link, use the ln command, which is the same command and syntax used for hard links, except that you include the -s option. Here's an example:

$ ln -s /tmp/hard ./dir/soft

$ ls -li dir/
total 0
25811328 lrwxrwxrwx. 1 localuser localuser 9 set 20 13:13 soft -> /tmp/hard

$ ln -s /home/localuser/dir/ /tmp/softdir

$ ls -li
total 0
25606589 drwxrwxr-x. 2 localuser localuser 18 set 20 13:13 dir

$ ls -li /tmp/
total 4
25606591 -rw-rw-r--. 1 localuser localuser  2 set 19 16:54 hard
 8410604 lrwxrwxrwx. 1 localuser localuser 20 set 20 13:18 softdir -> /home/localuser/dir/

If you're working in a shell with a colored ls command, the created symbolic link for a file or directory has an aqua or blue-green color, while the original file has a white color and the original directory has a dark blue color. These colors allow you to identify a symbolic link and the original content easily. Also, the created symbolic links for the file and the directory have different inode addresses than the originals.

Finally, the sizes and permissions are different for the file symbolic link, too. Compare the following examples:

$ stat dir/

  File: dir/
  Size: 18        	Blocks: 0          IO Block: 4096   directory
Device: fd00h/64768d	Inode: 25606589    Links: 2
Access: (0775/drwxrwxr-x)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-20 13:13:25.137000000 -0300
Modify: 2022-09-20 13:13:15.527000000 -0300
Change: 2022-09-20 13:13:15.527000000 -0300
 Birth: 2022-09-19 15:21:27.616000000 -0300

$ stat /tmp/softdir/

  File: /tmp/softdir/
  Size: 18        	Blocks: 0          IO Block: 4096   directory
Device: fd00h/64768d	Inode: 25606589    Links: 2
Access: (0775/drwxrwxr-x)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-20 13:13:25.137000000 -0300
Modify: 2022-09-20 13:13:15.527000000 -0300
Change: 2022-09-20 13:13:15.527000000 -0300
 Birth: 2022-09-19 15:21:27.616000000 -0300

$ stat /tmp/hard

  File: /tmp/hard
  Size: 2         	Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 25606591    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-19 16:56:22.024000000 -0300
Modify: 2022-09-19 16:54:59.123000000 -0300
Change: 2022-09-19 16:56:03.380000000 -0300
 Birth: 2022-09-19 15:29:40.276000000 -0300

$ stat dir/soft

  File: dir/soft -> /tmp/hard
  Size: 9         	Blocks: 0          IO Block: 4096   symbolic link
Device: fd00h/64768d	Inode: 25811328    Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2022-09-20 13:13:25.137000000 -0300
Modify: 2022-09-20 13:13:15.527000000 -0300
Change: 2022-09-20 13:13:15.527000000 -0300
 Birth: 2022-09-20 13:13:15.527000000 -0300

Note that the symbolic link created for the file does not consume any disk blocks and has a size of nine (the length of the /tmp/hard full path) precisely because it's only a pointer. You can manipulate the symbolic link the same way you would the original file, and the changes made to its contents are reflected in the original one:

$ cat dir/soft

0

$ cat /tmp/hard

0

$ echo 1 > dir/soft

$ cat dir/soft

1

$ cat /tmp/hard

1

Update a symbolic link

If you move a file or directory that a symbolic link points to, the connection is broken:

$ mv ~/dir ~/moved

$ cd /tmp/softdir
bash: cd: dir: No such file or directory

You can update a symbolic link using the -f option:

$ ln -sf ~/moved /tmp/softdir

$ ls -l /tmp/softdir
lrwxrwxrwx 1 localuser...3 Oct  3 18:42 softdir -> moved

[ Get the guide to installing applications on Linux. ]

Remove a file

When you delete the file a symbolic link points to, the connection is severed (and the data is gone instantly, unlike with a hard link). See how the two differ below:

$ rm /tmp/hard

$ ls -li /tmp/
total 0
8410604 lrwxrwxrwx. 1 localuser localuser 20 set 20 13:18 softdir -> /home/localuser/dir/

$ ls -li dir/
total 0
25811328 lrwxrwxrwx. 1 localuser localuser 9 set 20 13:13 soft ->

$ file dir/soft
dir/soft: broken symbolic link to /tmp/hard

$ cat dir/soft
cat: dir/soft: No such file or directory

If you're using a terminal with a colored ls command, you can see the output of a dark red color for the symbolic link name and a blinking white text with a light red background for the original file that doesn't exist anymore. The file command shows that your symbolic link is now broken. What happens if you try to write something into your broken symbolic link?

$ ls -li /tmp/

total 0
8410604 lrwxrwxrwx. 1 localuser localuser 20 set 20 13:18 softdir -> /home/localuser/dir/

$ echo 0 > dir/soft

$ ls -li dir/soft

25606591 lrwxrwxrwx. 1 localuser localuser 9 set 20 13:39 dir/soft -> /tmp/hard

$ file dir/soft

dir/soft: symbolic link to /tmp/hard

$ ls -li /tmp/hard

8410609 -rw-rw-r--. 1 localuser localuser 2 set 20 13:44 /tmp/hard

$ stat /tmp/hard

  File: /tmp/hard
  Size: 2         	Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 8410609     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/localuser)   Gid: ( 1000/localuser)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2022-09-20 13:44:55.300000000 -0300
Modify: 2022-09-20 13:44:55.300000000 -0300
Change: 2022-09-20 13:44:55.300000000 -0300
 Birth: 2022-09-20 13:44:55.300000000 -0300

It creates a new file with the same name in the same path that the symbolic link was pointing to with your newly added content.

But the same thing won't happen when it comes to directories:

$ rm -rf dir/

$ ls -li

$ ls -li /tmp/

total 4
8410609 -rw-rw-r--. 1 localuser localuser  2 set 20 13:44 hard
8410604 lrwxrwxrwx. 1 localuser localuser 20 set 20 13:18 softdir ->

$ cd /tmp/softdir

-bash: cd: /tmp/softdir: No such file or directory

$ file /tmp/softdir

/tmp/softdir: broken symbolic link to /home/localuser/dir/

$ echo 0 > /tmp/softdir/soft

-bash: /tmp/softdir/soft: No such file or directory

The same color scheme described before for broken links applies here. You won't be able to access the original directory through its broken symbolic link or by trying to create content inside the file that was there. It won't recreate a directory, meaning you've lost everything and the symbolic link is indeed broken, unless you create another directory (a new one) with the same name and the same location as the original one:

$ pwd
/home/localuser

$ mkdir dir

$ ls -li
total 0
21451985 drwxrwxr-x. 2 localuser localuser 6 set 20 13:55 dir

$ ls -li /tmp/
total 4
8410609 -rw-rw-r--. 1 localuser localuser  2 set 20 13:44 hard
8410604 lrwxrwxrwx. 1 localuser localuser 20 set 20 13:18 softdir -> /home/localuser/dir/

$ cd /tmp/softdir

$ pwd
/tmp/softdir

$ touch file

$ ls -li
total 0
21451986 -rw-rw-r--. 1 localuser localuser 0 set 20 13:56 file

$ ls -li /home/localuser/dir/
total 0
21451986 -rw-rw-r--. 1 localuser localuser 0 set 20 13:56 file

When working with symbolic links, make sure to always have the original content in place to avoid having broken links on your system.

Wrap up

As a sysadmin, you must understand and know how to create and manipulate hard and symbolic links, as well as the concepts behind them. This skill gives you a complete set of resources and possibilities to streamline, facilitate, improve, and automate the administration of your system. I hope this and my previous article about hard links helps you understand this topic, helps your Linux certification path, and adds to your general sysadmin knowledge.

Author’s photo

Alexon Oliveira

Alexon has been working as a Senior Technical Account Manager at Red Hat since 2018, working in the Customer Success organization focusing on Infrastructure and Management, Integration and Automation, Cloud Computing, and Storage Solutions. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.