Hard and symbolic links
Hard and symbolic links, and inodes.
Why this matters
Links show up everywhere in Linux. /etc/nginx/sites-enabled on Debian and Ubuntu is built
from symlinks, the current directory in a deploy points to the latest release, and
snapshot scripts save space with hard links. If you don't tell the two kinds of links apart,
it's easy to delete a "copy" along with the data, or end up with a link that leads nowhere.
inode and file name
An inode is the record that holds all of a file's metadata: size, permissions, owner, timestamps, and pointers to the data blocks. The file name itself isn't in the inode. The name lives in the directory: a directory stores pairs of "name → inode number".
You can see the inode number with the -i flag on ls:
ls -li notes.txt
1310745 -rw-r--r-- 1 deploy deploy 42 Jul 11 09:14 notes.txt
The first number (1310745) is the inode number. Next comes the link count column (1):
how many names point to this inode. The lesson linux-admin-08-fs-inodes goes into more
detail on how inodes work.
Hard link
A hard link (hardlink) is another name for the same inode. The ln command with no flags
creates such a name: two different paths lead to the same data.
ln notes.txt backup.txt
ls -li notes.txt backup.txt
1310745 -rw-r--r-- 2 deploy deploy 42 Jul 11 09:14 backup.txt
1310745 -rw-r--r-- 2 deploy deploy 42 Jul 11 09:14 notes.txt
The inode number is the same for both (1310745), and the link count went up to 2. Add
something to the file through one name, and the change shows up through the other, because
the data is shared.
The data exists as long as the link count is greater than zero. Removing one name lowers the count but doesn't touch the content:
rm notes.txt
ls -li backup.txt
1310745 -rw-r--r-- 1 deploy deploy 42 Jul 11 09:14 backup.txt
The count is back to 1, and the data is intact. It only gets freed once the last name
disappears (and no process still has the file open).
Symbolic link
A symbolic link (symlink) is a separate, small file that has the path to its target written
inside it. You create one with the -s flag:
ln -s /var/log/app/current app.log
ls -li app.log
1310902 lrwxrwxrwx 1 deploy deploy 20 Jul 11 09:20 app.log -> /var/log/app/current
A symlink has its own inode (1310902, unlike the target), the type l at the start of the
line, and an arrow to the path. The size 20 is the length of the path
/var/log/app/current in bytes, not the size of the target. When something accesses
app.log, the system resolves this path and lands on the target. readlink app.log shows
where the link points, and readlink -f app.log gives the full path to the final target.
A symlink can do what a hard link can't: point to a directory and cross filesystem
boundaries. A hard link only works inside one filesystem, because inode numbers are unique
within their own filesystem, not globally. ln says so directly:
ln /home/deploy/notes.txt /mnt/backup/notes.txt
ln: failed to create hard link '/mnt/backup/notes.txt' => '/home/deploy/notes.txt': Invalid cross-device link
ln /home/deploy logs
ln: /home/deploy: hard link not allowed for directory
The price of that flexibility: a symlink breaks if the target is removed or moved. The path inside stays the same, but it no longer leads anywhere:
rm /var/log/app/current
cat app.log
cat: app.log: No such file or directory
The link itself is still intact, only the target is gone. ls usually highlights such a
dangling link in red.
Relative path in a symlink
The path inside a symlink can be absolute (/var/log/app/current) or relative
(builds/2026-10). The system resolves a relative path from the directory where the link
itself lives, not from the directory you were in when you created it. That's why
ln -s builds/2026-10 /opt/app/live works no matter where you run it from, and the link
/opt/app/live points to /opt/app/builds/2026-10. If you move the whole /opt/app
directory, the relative links inside it keep working, while the absolute ones break.
How they differ
| Property | Hard link | Symbolic link |
|---|---|---|
| Command | ln A B | ln -s A B |
| What it points to | an inode | a path |
| Own inode | no, shared with the target | yes, separate |
| To a directory | not allowed | allowed |
| Across filesystems | not allowed | allowed |
| Target removed | data survives while count > 0 | link breaks |
Common mistakes
"A hard link and a symlink are the same thing." A hard link shares an inode with the
target, a symlink stores a path and has its own inode. Easy to check with ls -li: a hard
link's inode number matches the original, a symlink's doesn't.
"I deleted the file, and the hard link broke." A hard link has no concept of "original" and "copy", these are equal names for the same inode. As long as the link count is above zero, the data is intact:
ln data.bin data-hardlink.bin
rm data.bin
cat data-hardlink.bin
Here rm removes one name, and cat through the second name reads the data just like
before. Only a symlink breaks from a deletion, because it holds a path, not the data itself.
Argument order. ln takes the target first, then the name of the new link, just like
cp: ln -s builds/2026-10 live. Mix up the arguments, and the link shows up somewhere you
don't expect: if the second argument is an existing directory, ln creates the link inside
it.
What you'll need for the tasks
ls -liandstat -c '%i %h %n' <file>: inode number, link count, name.ln A Bfor a hard link andln -s A Bfor a symlink.readlinkandreadlink -f: where a symlink points.- A relative path in a symlink is resolved from the link's directory.
- A hard link doesn't work across filesystems or on directories.
The next lesson covers the virtual filesystems /proc and /sys.
Interview-style questions
Interview questions on this topic: 1
Included with practice access, $49 one-time. Get access
Answer out loud or in writing, then reveal the answer and honestly mark whether you knew it.
Done reading?
Mark the lesson as read to move your track progress forward.
Lesson marked as done.
Go through it with an AI agent
The agent explains anything unclear in plain words, gives you 2 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.
Tell the agent: use MCP izi, give me lesson linux-fs-deep-02-links
Progress saved in this browser
Clear your history or open this on your phone, and the marks will be gone. Leave your email and they'll move to your account. No password needed.
Done. moved to your account. You can see your progress on any device. My progress