Links between files

Chester Wyke February 24, 2024 Updated: April 15, 2025 #debian

TLDR

Usage: ln [OPTION]… [-T] TARGET LINK_NAME or: ln [OPTION]… TARGET or: ln [OPTION]… TARGET… DIRECTORY or: ln [OPTION]… -t DIRECTORY TARGET… In the 1st form, create a link to TARGET with the name LINK_NAME. In the 2nd form, create a link to TARGET in the current directory. In the 3rd and 4th forms, create links to each TARGET in DIRECTORY. Create hard links by default, symbolic links with –symbolic. By default, each destination (name of new link) should not already exist. When creating hard links, each TARGET must exist. Symbolic links can hold arbitrary text; if later resolved, a relative link is interpreted in relation to its parent directory.

Example from the folder to create link in (same for directory or file)

ln -s ORIGINAL ./

Hard links vs Soft Links (Symbolic Link / Symlinks)

The man page for ln is really good and I can’t add much to it. It links to the full documentation which is also really good.

The most succinct explanation I found was on SO and is quoted below for ease of reference. The full documentation linked by the man page included the same info but was longer. However the documentation is more authoritative. In particular see examples at the end of the full documentation.

Underneath the file system, files are represented by inodes. (Or is it multiple inodes? Not sure.)

A file in the file system is basically a link to an inode. A hard link, then, just creates another file with a link to the same underlying inode.

When you delete a file, it removes one link to the underlying inode. The inode is only deleted (or deletable/over-writable) when all links to the inode have been deleted.

A symbolic link is a link to another name in the file system.

Once a hard link has been made the link is to the inode. Deleting, renaming, or moving the original file will not affect the hard link as it links to the underlying inode. Any changes to the data on the inode is reflected in all files that refer to that inode.

Note: Hard links are only valid within the same File System. Symbolic links can span file systems as they are simply the name of another file.

Other good references that I found were:

Determine number of hard links to a file

Source:https://ftp.gnu.org/old-gnu/Manuals/findutils-4.1/html_node/find_13.html

Note: There more information in the source article but this is what I wanted from it.

Use -i on ls to see the inode number of a file. That is actually what stores the information in the file and the file system links to that. Use -li to also see how many hard links there are to the file.

In the example below the first column is the inode number and the 3rd is the number of hard links. a is separate but after b was created I ran ln b c so c is just another link to b and then I ran ln -s b d so d is a soft link to b. If b goes away then d also stops working but c lives on (along with the data).

% ls -li
total 12
5262999 -rw-rw-r-- 1 one one 91 Feb 24 08:33 a
5304232 -rw-rw-r-- 2 one one  5 Feb 24 09:47 b
5304232 -rw-rw-r-- 2 one one  5 Feb 24 09:47 c

Example of trying ln command

% echo "Text for separate file a" > a
% echo "Text for all the other files" > b
% ln b c
% ln -s b d
% ls -li
total 12
18879400 -rw-rw-r-- 1 one one 25 Feb 24 10:11 a
18879529 -rw-rw-r-- 2 one one 29 Feb 24 10:11 b
18879529 -rw-rw-r-- 2 one one 29 Feb 24 10:11 c
18879531 lrwxrwxrwx 1 one one  1 Feb 24 10:11 d -> b
% ls -l
total 12
-rw-rw-r-- 1 one one 25 Feb 24 10:11 a
-rw-rw-r-- 2 one one 29 Feb 24 10:11 b
-rw-rw-r-- 2 one one 29 Feb 24 10:11 c
lrwxrwxrwx 1 one one  1 Feb 24 10:11 d -> b
% cat a
Text for separate file a
% cat b
Text for all the other files
% cat c
Text for all the other files
% cat d
Text for all the other files
% rm b # Delete first copy of file
% cat c # Still works
Text for all the other files
% cat d # Broken because source file is gone
cat: d: No such file or directory
% ls -li
total 8
18879400 -rw-rw-r-- 1 one one 25 Feb 24 10:11 a
18879529 -rw-rw-r-- 1 one one 29 Feb 24 10:11 c
18879531 lrwxrwxrwx 1 one one  1 Feb 24 10:11 d -> b