Linux ln Command
last modified October 23, 2026
The ln command in Linux creates links between files. There are
two kinds of links. A hard link is an additional name for
the same file data; a symbolic link (symlink, soft link) is
a small special file that contains a path to another file or directory.
On Linux file systems, file data and metadata are stored in an
inode, and a directory entry maps a name to an inode number. Hard
links are several directory entries pointing to one inode. Symbolic links
point to a path, which is resolved each time the link is used. The syntax
is ln [options] target link_name; the target comes first, as
with cp.
Creating a hard link
Without options, ln creates a hard link.
ln data.txt data-hard.txt
The -i option of ls prints the inode number in the
first column. Both names share the same inode, and the link count in the
third column is 2. Neither name is the original; they are equal.
$ ln data.txt data-hard.txt $ ls -li data.txt data-hard.txt 2626980 -rw-r--r-- 2 jano jano 17 Oct 23 09:00 data-hard.txt 2626980 -rw-r--r-- 2 jano jano 17 Oct 23 09:00 data.txt
Hard links share data
Since both names refer to the same inode, a change made through one name is visible through the other.
echo "appended line" >> data-hard.txt rm data.txt
The appended line appears in data.txt. Removing
data.txt only deletes one name and decrements the link count;
the data stays available through data-hard.txt. The file
content is freed when the last link is removed and no process has the file
open.
$ echo "appended line" >> data-hard.txt $ cat data.txt original content appended line $ rm data.txt $ cat data-hard.txt original content appended line $ ls -li data-hard.txt 2626980 -rw-r--r-- 1 jano jano 31 Oct 23 11:46 data-hard.txt
Creating a symbolic link
The -s option creates a symbolic link.
ln -s data-hard.txt data-link.txt
The listing starts with l and shows the target after the arrow.
The size of the link is the length of the stored path. The permissions of a
symlink are always shown as rwxrwxrwx and are not used; access
is governed by the permissions of the target. Reading the link reads the
target.
$ ln -s data-hard.txt data-link.txt $ ls -l data-link.txt lrwxrwxrwx 1 jano jano 13 Oct 23 11:46 data-link.txt -> data-hard.txt $ cat data-link.txt original content appended line
Linking to a directory
Symbolic links can point to directories, which is a common way to create shortcuts to deeply nested paths.
ln -s projects/app/config conf
The link conf behaves like the directory itself. Note that
ls -l conf shows the link, while ls conf/ with a
trailing slash lists the contents of the target directory.
$ ln -s projects/app/config conf $ ls -l conf lrwxrwxrwx 1 jano jano 19 Oct 23 11:46 conf -> projects/app/config $ ls conf/ app.conf $ cat conf/app.conf port=8080
Dangling links
A symbolic link stores only a path. If the target is moved or deleted, the link is left dangling.
mv data-hard.txt moved.txt find . -xtype l
After the target is renamed, the link still exists but points nowhere, so
reading it fails. The -xtype l test of find lists
broken symbolic links. A hard link would not break, because it refers to the
inode, not to the name.
$ mv data-hard.txt moved.txt $ ls -l data-link.txt lrwxrwxrwx 1 jano jano 13 Oct 23 11:46 data-link.txt -> data-hard.txt $ cat data-link.txt cat: data-link.txt: No such file or directory $ find . -xtype l ./data-link.txt
Relative symbolic links
A relative path in a symlink is resolved from the directory containing the link, not from the current directory.
ln -s projects/app/config/app.conf bin/broken.conf ln -sr projects/app/config/app.conf bin/app.conf
The first link is created inside bin, so its target is looked up
as bin/projects/..., which does not exist. The
-r option computes the correct relative path,
../projects/..., for us. Relative links keep working when the
whole tree is moved or copied elsewhere; absolute links do not depend on the
location of the link.
$ mkdir -p bin $ ln -s projects/app/config/app.conf bin/broken.conf $ cat bin/broken.conf cat: bin/broken.conf: No such file or directory $ ln -sr projects/app/config/app.conf bin/app.conf $ ls -l bin total 0 lrwxrwxrwx 1 jano jano 31 Oct 23 11:46 app.conf -> ../projects/app/config/app.conf lrwxrwxrwx 1 jano jano 28 Oct 23 11:46 broken.conf -> projects/app/config/app.conf $ cat bin/app.conf port=8080
Reading link targets
The readlink command prints the target stored in a link.
readlink bin/app.conf readlink -f bin/app.conf realpath conf
Plain readlink prints the path as stored. With
-f, it follows all links and prints the canonical absolute
path; realpath does the same.
$ readlink bin/app.conf ../projects/app/config/app.conf $ readlink -f bin/app.conf /home/jano/work/projects/app/config/app.conf $ realpath conf /home/jano/work/projects/app/config
Replacing a directory link
Switching a link such as current from one release directory to
another is a common deployment technique. It needs the -f and
-n options.
ln -s releases/v1 current ln -s releases/v2 current ln -sfn releases/v2 current
The second command does not replace the link. Since current
resolves to a directory, ln creates a new link named
v2 inside releases/v1. The -f option
removes an existing destination, and -n treats a symlink to a
directory as a normal file, so the link itself is replaced. The replacement
removes the old link before creating the new one; for a switch without even a
brief gap, create a temporary link and rename it with
mv -T current.tmp current.
$ mkdir -p releases/v1 releases/v2 $ ln -s releases/v1 current $ ln -s releases/v2 current $ ls releases/v1 v2 $ rm releases/v1/v2 $ ln -sfn releases/v2 current $ ls -l current lrwxrwxrwx 1 jano jano 11 Oct 23 11:46 current -> releases/v2
Linking multiple files
With several targets, the last argument must be a directory, in which links with the same names are created.
ln -sv /etc/hostname /etc/os-release links/
The -v option prints each created link.
$ mkdir links $ ln -sv /etc/hostname /etc/os-release links/ 'links/hostname' -> '/etc/hostname' 'links/os-release' -> '/etc/os-release'
Hard link limitations
Hard links have two restrictions: they cannot point to directories, and they cannot cross file system boundaries.
ln projects hardlink-dir ln moved.txt /dev/shm/moved.txt
Inode numbers are unique only within one file system, so a hard link to
another file system is impossible; /dev/shm is a separate
in-memory file system, as df shows. Symbolic links have neither
limitation, which is why they are used much more often.
$ ln projects hardlink-dir ln: projects: hard link not allowed for directory $ df --output=target . /dev/shm | tail -n +2 / /dev/shm $ ln moved.txt /dev/shm/moved.txt ln: failed to create hard link '/dev/shm/moved.txt' => 'moved.txt': Invalid cross-device link
Best practices for ln
- Remember the order: The target comes first and the link name second.
- Prefer symbolic links: They work across file systems and for directories, and their target is visible.
- Use -r for relative links: Let
lncompute the correct relative path. - Use -sfn to switch links: Replace links to directories instead of creating links inside them.
- Check for broken links: Use
find -xtype lafter moving files.
Source
In this article, we have used the ln command to create hard and
symbolic links, worked with relative and dangling links, and replaced links
to directories.
Author
List all Linux tutorials.