What is ln
ln creates links between files. A link is an additional name pointing to the same data. Linux supports two kinds: hard links and symbolic links (symlinks).
Hard links vs symbolic links
To understand the difference, it helps to know that Linux files have two parts: an inode (metadata + pointer to data) and the file data itself. A filename is just a pointer to an inode.
Hard link — a second filename pointing to the same inode:
- Both names are equal; neither is "the original"
- Deleting one name leaves the other intact — the data survives until the last name is removed
- Cannot span different filesystems
- Cannot point to directories
Symbolic link — a special file that contains a path to another file:
- Deleting the target breaks the symlink (dangling link)
- Can cross filesystems
- Can point to directories
- Shows as
linls -la
Create a symbolic link
ln -s target link_name
Examples:
ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite
ln -s /opt/myapp/bin/myapp /usr/local/bin/myapp
ln -s ~/dotfiles/.bashrc ~/.bashrc
Create a hard link
ln target link_name
Example:
ln report.pdf report-backup.pdf
Both files now share the same inode. Changes to either are visible in both.
Link a directory (symlink only)
ln -s /data/media /home/user/media
Hard links to directories are not allowed (except for . and .. maintained by the kernel).
Verify links
ls -la
A symlink shows as:
lrwxrwxrwx 1 user user 20 Jul 7 10:00 myapp -> /opt/myapp/bin/myapp
Check what a symlink points to:
readlink /usr/local/bin/myapp
readlink -f /usr/local/bin/myapp # resolve all symlinks, show absolute path
Overwrite an existing link
ln -sf new_target link_name
The -f flag removes the existing link before creating the new one.
Practical examples
Manage Nginx virtual hosts (the Debian/Ubuntu pattern):
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Put a script on your PATH without moving it:
ln -s ~/scripts/deploy.sh /usr/local/bin/deploy
Keep dotfiles in a version-controlled directory:
ln -s ~/dotfiles/.vimrc ~/.vimrc
ln -s ~/dotfiles/.bashrc ~/.bashrc
Switch between Python versions:
ln -sf /usr/bin/python3.12 /usr/local/bin/python3
See also
man ln, readlink(1), stat(1) — check inode numbers with stat filename to confirm two names share the same inode.
- Created: May 16, 2007
- Last edited: July 7, 2026