Symbolic Links and Hard Links - Understanding File References in Linux

Symbolic Links and Hard Links - Understanding File References in Linux

The Short Answer

A symbolic link stores a path string (like a shortcut); a hard link is an additional directory entry pointing to the same inode (the same data under a different name). When in doubt, use a symbolic link (ln -s).

When to use which

  • Cross-filesystem links, or links to directories → symbolic link
  • Incremental backups where deleted originals must not destroy data → hard link
  • Not sure → symbolic link

ln Command Syntax

The ln command creates both symbolic and hard links.

# Symbolic link (-s is required)
ln -s [target] [link_name]

# Hard link (no -s)
ln [target] [link_name]

Omitting -s silently creates a hard link. If the target is a directory it will fail with an error, but for regular files the mistake goes unnoticed.

A symbolic link is a special file that stores a path string. The OS resolves that path at each access — similar to a Windows shortcut, but handled transparently by the kernel.

$ ln -s /etc/nginx/nginx.conf ./nginx.conf
$ ls -la
lrwxrwxrwx 1 user user 22 Jan  1 00:00 nginx.conf -> /etc/nginx/nginx.conf

The l at the start of the permissions string indicates a symlink. The -> shows the stored path.

Property Details
Cross-filesystem Yes (different mount points OK)
Link to directory Yes
If target is deleted Link becomes dangling (broken)
Resolution Path is re-resolved at every access
# Show the stored path
$ readlink nginx.conf
/etc/nginx/nginx.conf

# Resolve to absolute path
$ readlink -f nginx.conf
/etc/nginx/nginx.conf

A hard link is an additional directory entry pointing to the same inode. Both names refer to the exact same data — one inode, two names.

$ echo "hello" > original.txt
$ ln original.txt hardlink.txt
$ ls -lai
1234567 -rw-r--r-- 2 user user 6 Jan  1 00:00 hardlink.txt
1234567 -rw-r--r-- 2 user user 6 Jan  1 00:00 original.txt

The leading number (1234567) is the inode number — identical numbers mean identical data. The link count (2) shows how many directory entries reference this inode.

Property Details
Cross-filesystem No (same partition only)
Link to directory No (restricted for regular users)
If original is deleted Data persists until link count reaches 0
Resolution Direct inode access (no path traversal)

Comparison: Symlink vs Hard Link

The core difference is what each one references.

Aspect Symbolic Link Hard Link
References Path string inode
Cross-filesystem Yes No
Directory target Yes No
After target deleted Becomes dangling Data survives
ls permissions Starts with l Same as regular file
inode Own inode (separate) Same inode as target

Practical Use Cases

Dotfiles management

$ ln -s ~/dotfiles/.bashrc ~/.bashrc
$ ln -s ~/dotfiles/.vimrc ~/.vimrc

Version-managed "current" directory

# Point current to version 1.2.0
$ ln -s /opt/app-1.2.0 /opt/app/current

# Upgrade: re-point the link atomically
$ ln -sfn /opt/app-1.3.0 /opt/app/current

-f overwrites an existing link; -n prevents following a directory target, so the link itself is replaced rather than a new link being created inside the directory.

Incremental backups with rsync

$ rsync -a --link-dest=/backup/prev/ /data/ /backup/today/

Files unchanged since the previous backup are hard-linked rather than copied, so each day's snapshot is space-efficient while remaining independent.

Common Pitfalls

# Created from /home/user
$ ln -s ../etc/nginx/nginx.conf nginx.conf

# Breaks when accessed from /tmp
$ cd /tmp
$ cat nginx.conf
cat: nginx.conf: No such file or directory

The symlink records the exact path string you passed to ln — not a path relative to where the link file lives. Use absolute paths for symlinks that must work from multiple locations.

# Wrong: if current is a directory, ln -sf creates a link INSIDE it
$ ln -sf /opt/app-2.0.0 /opt/app/current

# Right: -n replaces the link itself
$ ln -sfn /opt/app-2.0.0 /opt/app/current
$ find /path -maxdepth 1 -xtype l

-xtype l matches symlinks whose target does not exist (-type l alone includes all symlinks, both valid and broken).

Next Reading