1. Overview
Creating symbolic links allows us to access files more flexibly, even if the target files are in a different file system.
In this tutorial, we’ll have a look at how to remove a symbolic link.
2. Introduction to the Problem
Let’s say we have an aDir directory and an aFile.txt file under the current working directory. Also, we’ve created two symbolic links pointing to the file and the directory:
$ ls -l
total 0
drwxr-xr-x 2 kent kent 40 Apr 26 23:48 aDir/
-rw-r--r-- 1 kent kent 0 Apr 26 23:46 aFile.txt
lrwxrwxrwx 1 kent kent 4 Apr 26 23:48 dirLink -> aDir/
lrwxrwxrwx 1 kent kent 9 Apr 26 23:48 fileLink -> aFile.txt
Our goal is to remove the two soft links.
There are several ways to achieve that. Next, let’s see them in detail.
3. Using the rm Command
We know the rm command can delete files and directories. Additionally, we can use this command to delete symbolic links.
First, let’s remove fileLink using the rm command:
$ rm fileLink
$ ls -l
total 0
drwxr-xr-x 2 kent kent 40 Apr 26 23:48 aDir/
-rw-r--r-- 1 kent kent 0 Apr 26 23:46 aFile.txt
lrwxrwxrwx 1 kent kent 4 Apr 26 23:48 dirLink -> aDir/
As the output above shows, We have successfully deleted fileLink. The syntaxes of deleting a symbolic link and a file are the same.
Next, let’s remove the dirLink link:
$ rm dirLink/
rm: cannot remove 'dirLink/': Is a directory
Oops! The rm command refuses to remove the link and prints an error message. The message looks weird since we don’t have the dirLink directory at all. What’s wrong with the command?
The problem is, we’ve added a forward slash after the link name.
When we attempt to delete symbolic links using the rm command, we should pass the link name to rm. No matter if the target is a file or a directory, we shouldn’t include the slash.
Now that we understand the cause of the problem, let’s fix it and try the command again:
$ rm dirLink
$ ls -l
total 0
drwxr-xr-x 2 kent kent 40 Apr 26 23:48 aDir/
-rw-r--r-- 1 kent kent 0 Apr 26 23:46 aFile.txt
Great! The dirLink link has now been removed.
4. Using the unlink Command
The unlink command is a member of the CoreUtils package, and it’s available on all Linux distros.
Let’s re-create the two links and try to delete them using the unlink command.
First, we’re going to delete the fileLink link:
$ unlink fileLink
$ ls -l
total 0
drwxr-xr-x 2 kent kent 40 Apr 26 23:48 aDir/
-rw-r--r-- 1 kent kent 0 Apr 26 23:46 aFile.txt
lrwxrwxrwx 1 kent kent 4 Apr 27 00:15 dirLink -> aDir/
The command is pretty straightforward, and it works.
Now, let’s try passing “dirLink/” to unlink to see if it can remove the link:
$ unlink dirLink/
unlink: cannot unlink 'dirLink/': Not a directory
Similarly, if we pass a name ending with a slash, the unlink command refuses to remove the link, too.
Therefore, we should only pass the link name to unlink:
$ unlink dirLink
$ ls -l
total 0
drwxr-xr-x 2 kent kent 40 Apr 26 23:48 aDir/
-rw-r--r-- 1 kent kent 0 Apr 26 23:46 aFile.txt
It’s worth mentioning that if we pass the name of a regular file to the unlink command, it’ll delete the file, even though it’s not a link:
$ unlink aFile.txt
$ ls -l
total 0
drwxr-xr-x 3 kent kent 60 Apr 27 00:22 ./
drwxrwxrwt 23 root root 840 Apr 27 00:18 ../
drwxr-xr-x 2 kent kent 40 Apr 26 23:48 aDir/
5. Deleting Multiple Links in One Shot
We know that we can use the find | xargs rm combination to delete files in the find command’s result. Similarly, we can remove symbolic links using the same technique.
Now, let’s see another example:
$ tree
.
├── 2bDeleted_01.txt -> aFile.txt
├── 2bDeletedDir -> aDir
├── 2bDeletedDir_01 -> aDir
├── 2bDeletedDir_02 -> aDir
├── 2bDeleted_I_am_not_a_link.txt
├── 2bDeleted.txt -> aFile.txt
├── aDir
│ ├── 2bDeleted_etc -> /etc
│ └── keepMe_etc -> /etc
├── aFile.txt
├── keepMeDir -> aDir
└── keepMe.txt -> aFile.txt
7 directories, 5 files
The output above shows that we have multiple links in the current directory and the sub-directory “aDir”. Also, some link names are with the pattern “2bDeleted*”, while other link names follow the pattern “*keepMe**“.
Our goal is to recursively remove all symbolic links whose names match the pattern “*2bDeleted**“.
We should be careful that we only want to remove symbolic links. For example, we should keep the regular file 2bDeleted_I_am_not_a_link.txt intact, even though its name begins with “2bDeleted“.
Next, let’s see how we achieve the goal using the *find | xargs rm (*or unlink) combination.
The first step is to build the find command to locate all the links we want to delete:
$ find . -type l -name '2bDeleted*'
./2bDeleted.txt
./2bDeleted_01.txt
./2bDeletedDir
./2bDeletedDir_01
./2bDeletedDir_02
./aDir/2bDeleted_etc
We pass two expressions to the find command:
- -type l: We search symbolic links only
- -name ‘2bDeleted*’: The link name matches the given pattern
Next, we can pipe the result to the xargs command:
$ find . -type l -name '2bDeleted*' | xargs -I{} rm "{}"
$ tree
.
├── 2bDeleted_I_am_not_a_link.txt
├── aDir
│ └── keepMe_etc -> /etc
├── aFile.txt
├── keepMeDir -> aDir
└── keepMe.txt -> aFile.txt
3 directories, 3 files
As the tree output shows, the command works as we expected.
6. Conclusion
In this article, we’ve learned that when we want to remove a symbolic link, we can consider picking the rm or the unlink command.
However, we should keep in mind that no matter which command we use, we should only pass the link names and not include a trailing forward slash.
Additionally, we addressed how to recursively delete symbolic links in one shot through an example.