Linux ln Command Deep Dive: Understanding Hard Links and Symbolic Links#

2026-05-09 12:57

Ever wondered why deleting a file sometimes doesn’t truly remove it? That’s the magic of Linux links. The ln command is one of the core tools in the Linux filesystem arsenal. Understanding it unlocks the secrets of inodes, filesystem architecture, and even how Docker image layers work.

Before diving into ln, we need to understand inodes. Every file in Linux has a unique inode number that stores metadata (permissions, owner, timestamps, data block locations) but not the filename.

# View a file's inode number
ls -i myfile.txt
# Output: 131074 myfile.txt

stat myfile.txt
# Output includes: Inode: 131074

Filenames are just entries in directories pointing to inodes. A single inode can be pointed to by multiple filenames—that’s the essence of hard links.

Hard links create multiple filenames pointing to the same inode—they’re completely equivalent at the filesystem level:

# Create a hard link
ln original.txt hardlink.txt

# Verify: both share the same inode
ls -li original.txt hardlink.txt
# 131074 -rw-r--r-- 2 user group 100 May 9 12:00 hardlink.txt
# 131074 -rw-r--r-- 2 user group 100 May 9 12:00 original.txt

Notice the 2 in the second column—that’s the link count, showing how many directory entries point to this inode.

  1. Complete Equivalence: No distinction between “original” and “link”—deleting either doesn’t affect the other
  2. Synchronized Updates: Modifying one file is visible through all links
  3. Space Efficiency: No data copying, just adding a directory entry
  4. Limitations: Cannot cross filesystems, cannot point to directories (prevents cycles)
# Hard link remains valid after deleting the original
rm original.txt
cat hardlink.txt  # Content fully intact

# Link count decreases by 1
ls -l hardlink.txt
# -rw-r--r-- 1 user group 100 May 9 12:00 hardlink.txt

Symbolic links (soft links) are independent files that store the target path as a string:

# Create a symbolic link
ln -s /path/to/target.txt symlink.txt

# View link information
ls -l symlink.txt
# lrwxrwxrwx 1 user group 15 May 9 12:00 symlink.txt -> /path/to/target.txt

Notice the l at the start of permissions—this indicates a link file. Symbolic links have their own inode, and their size equals the length of the target path string.

  1. Can Cross Filesystems: It’s just storing a path string
  2. Can Point to Directories: Commonly used for directory aliases
  3. Become “Broken Links” When Target Doesn’t Exist: The link exists but can’t be accessed
  4. Can Link to Network Paths: NFS, SMB, etc.
# Create a directory symbolic link
ln -s /var/log/apache2 /var/www/logs

# Practical use: version switching
ln -s /usr/local/node-20/bin/node /usr/local/bin/node
# When upgrading, just change the symlink target

Under the Hood: Directory Entries and Inode Tables#

From the kernel’s perspective, ln modifies directory entries:

// Hard link: Create new entry in directory pointing to existing inode
// Simplified kernel logic
int sys_link(const char *oldpath, const char *newpath) {
    // 1. Find the original file's inode
    inode_t *inode = namei(oldpath);
    if (!inode) return -ENOENT;
    
    // 2. Create new directory entry in target directory
    dir_entry_t entry;
    entry.inode = inode->ino;
    strcpy(entry.name, basename(newpath));
    
    // 3. Increment link count
    inode->i_links++;
    
    return 0;
}

Symbolic links create a new inode and data block:

// Symbolic link: Create new inode, data block stores target path
int sys_symlink(const char *target, const char *linkpath) {
    // 1. Allocate new inode
    inode_t *inode = ialloc();
    inode->i_mode = S_IFLNK | 0777;
    
    // 2. Write target path to data block
    write_data(inode, target, strlen(target));
    
    // 3. Create directory entry
    add_dir_entry(linkpath, inode);
    
    return 0;
}

Practical Scenarios#

1. Version Switching#

# Multiple versions coexisting
ls -l /usr/local/
# drwxr-xr-x  node-18
# drwxr-xr-x  node-20
# lrwxrwxrwx  node -> node-20

# One-command switch
rm /usr/local/node
ln -s /usr/local/node-18 /usr/local/node

2. Disk Space Expansion#

# Migrate logs to new disk
mv /var/log/app /data/logs/app
ln -s /data/logs/app /var/log/app

# Application is unaware, path unchanged

3. Incremental Backups#

# Hard links for incremental backups
cp -al backup-2026-05-08/ backup-2026-05-09/
# -a preserves attributes, -l creates hard links instead of copying

# rsync updates only changed files
rsync -a --delete /data/ backup-2026-05-09/

# Unchanged files share inodes, zero extra space

4. Docker Image Layer Mechanism#

Docker’s layered storage is built on hard links:

# Docker layers stored in /var/lib/docker/overlay2/
# Multiple images share identical base layer files (hard links)
ls -li /var/lib/docker/overlay2/*/diff/usr/bin/python3
# python3 in multiple image layers is the same inode

Common Pitfalls#

# Wrong: relative path based on current directory, not link location
ln -s ../config.json /app/config/link.json

# Correct: use absolute paths or paths relative to the link
ln -s /app/config.json /app/link/link.json
ln -s /tmp/myapp /var/myapp
rm -rf /tmp/myapp
# /var/myapp becomes a broken link

ls -l /var/myapp
# lrwxrwxrwx 1 user group 9 May 9 12:00 /var/myapp -> /tmp/myapp
# Link exists but target is gone
# Directory link count includes . and ..
mkdir mydir
ls -ld mydir
# drwxr-xr-x 2 user group 4096 May 9 12:00 mydir
#               ^ Link count is 2: mydir + mydir/.

mkdir mydir/subdir
ls -ld mydir
# drwxr-xr-x 3 user group 4096 May 9 12:00 mydir
#               ^ Link count is 3: mydir + mydir/. + mydir/subdir/..

ln Command Parameters Reference#

Flag Purpose Example
-s Create symbolic link ln -s target link
-f Force overwrite existing link ln -sf target link
-n Don’t dereference target (link to link itself) ln -sn link1 link2
-v Show operation details ln -sv target link
-b Backup overwritten files ln -sb target link

While browsers can’t directly create filesystem links, we can model the concept in JavaScript:

// Simulated filesystem
interface FileSystem {
  inodes: Map<number, Inode>;
  directories: Map<string, DirEntry[]>;
}

interface Inode {
  id: number;
  type: 'file' | 'directory' | 'symlink';
  data?: string;
  linkCount: number;
  target?: string;  // Symbolic link target path
}

// Create hard link
function createHardLink(fs: FileSystem, source: string, target: string) {
  const sourceEntry = findDirEntry(fs, source);
  if (!sourceEntry) throw new Error('Source not found');
  
  // Point to the same inode
  const targetDir = dirname(target);
  const targetName = basename(target);
  
  fs.directories.get(targetDir)?.push({
    name: targetName,
    inodeId: sourceEntry.inodeId
  });
  
  // Increment link count
  fs.inodes.get(sourceEntry.inodeId)!.linkCount++;
}

// Create symbolic link
function createSymlink(fs: FileSystem, target: string, link: string) {
  // Create new inode
  const inodeId = fs.inodes.size + 1;
  fs.inodes.set(inodeId, {
    id: inodeId,
    type: 'symlink',
    target: target,
    linkCount: 1
  });
  
  // Add directory entry
  const linkDir = dirname(link);
  const linkName = basename(link);
  fs.directories.get(linkDir)?.push({
    name: linkName,
    inodeId: inodeId
  });
}

Performance Considerations#

Operation Time Complexity Notes
Create hard link O(1) Only adds directory entry, increments counter
Create symbolic link O(1) Creates new inode, writes path
Delete hard link O(1) Decrements counter, may free inode
Access symbolic link O(n) n is link depth, follows chain

Summary#

The core value of the ln command:

  1. Space Efficiency: Hard links share data at zero space cost
  2. Flexibility: Symbolic links cross filesystems and link to directories
  3. Version Management: Switch versions via symlinks without changing environment variables
  4. Backup Optimization: Hard links enable incremental backups

Mastering ln isn’t just about learning a tool—it’s your gateway to understanding Linux filesystem architecture. Concepts like inodes, directory entries, and link counts appear everywhere from databases to distributed storage to container technologies.


Related Tools: