Links: Hard vs. Symbolic
Two different ways for one file to be reachable from multiple paths - a hard link shares the same underlying data, a symbolic link is just a pointer to a path.
Both let you refer to "the same file" from two different paths, but they work in fundamentally different ways, with different tradeoffs - mixing them up leads to confusing surprises, especially when deleting or moving files.
Inodes, briefly
Every file's actual data and metadata (permissions, owner, size, timestamps) live in a structure called an inode, identified by an inode number, not by its filename. A directory entry is just a mapping from a name to an inode number. See it directly:
ls -li /etc/hostname
131074 -rw-r--r-- 1 root root 12 Jan 2 10:00 /etc/hostname
That first number, 131074, is the inode number.
Hard links: another name for the same inode
ln original.txt hardlink.txt
ls -li original.txt hardlink.txt
131074 -rw-r--r-- 2 root root 12 Jan 2 10:00 hardlink.txt
131074 -rw-r--r-- 2 root root 12 Jan 2 10:00 original.txt
Same inode number, and the link count (the 2 right after permissions)
shows two names now point to it. There's no "original" and "copy" once
this is done - both names are equally real, editing either changes the
same underlying data, and the data isn't actually deleted until every
hard link to it is removed.
Hard links have real limitations: they can't cross filesystem boundaries (an inode number only means something within its own filesystem - see Mounting and fstab), and most systems don't allow hard-linking directories at all, to avoid creating loops in the directory tree.
Symbolic links: a pointer to a path
ln -s /etc/nginx/sites-available/mysite.conf mysite-enabled.conf
ls -li mysite-enabled.conf
131099 lrwxrwxrwx 1 root root 42 Jan 2 10:00 mysite-enabled.conf -> /etc/nginx/sites-available/mysite.conf
A different inode entirely, of type l (symlink), whose "content" is just
the target path as text. This is exactly the mechanism Nginx and Apache
use for enabling sites (sites-available holds the real config,
sites-enabled holds symlinks into it).
Consequences of being a path rather than an inode reference:
- Works across filesystems, and can even point to a path that doesn't exist yet or no longer exists (a "dangling" symlink)
- Deleting the target leaves a broken link behind - the link itself still exists, it just points nowhere
- Deleting the symlink doesn't touch the target at all
- A relative-path symlink (
ln -s ../shared/file.txt link) resolves relative to the symlink's own location, not your current directory, which can be surprising if you move the symlink
Choosing between them
| Hard link | Symbolic link | |
|---|---|---|
| Crosses filesystems | No | Yes |
| Can target a directory | No (generally) | Yes |
| Survives target being deleted | N/A - it is the data | No - becomes dangling |
What ls -l shows |
Identical to the original | Shows -> target explicitly |
In practice, symbolic links are the default choice for most everyday
use - configuration shortcuts, version "current" pointers, linking a
binary into /usr/local/bin. Hard links show up more in specialized
cases like backup tools that use them to avoid duplicating unchanged
files between snapshots.
Finding links
find / -xdev -xtype l # broken symlinks (target doesn't exist)
find / -xdev -samefile original.txt # every hard link to a given inode