Skip to content
beginner Phase 2 · Linux Fundamentals

Filesystem Hierarchy Standard

Navigate the FHS directory structure including /etc, /var, /usr, /opt, and understand the purpose of each directory.

45m
0 problems
Topic Progress 0%

The Filesystem Hierarchy Standard

Filesystem Hierarchy Standard (FHS)

Linux organizes files in a single rooted tree, unlike Windows drive letters. Every file and directory starts from / (root).

Key Directories

/                 # Root of the entire filesystem
├── bin/          # Essential user binaries (ls, cp, mv)
├── sbin/         # System binaries (fdisk, iptables)
├── etc/          # System configuration files
│   ├── ssh/      # SSH server config
│   ├── nginx/    # Web server config
│   └── fstab     # Filesystem mount table
├── var/          # Variable data: logs, databases, mail
│   ├── log/      # System and application logs
│   └── lib/      # Package manager data
├── tmp/          # Temporary files (cleared on reboot)
├── home/         # User home directories
│   └── ubuntu/
├── root/         # Root user's home directory
├── usr/          # User-space programs and libraries
│   ├── bin/      # Non-essential user binaries
│   ├── lib/      # Libraries
│   └── share/    # Architecture-independent data
├── opt/          # Optional/third-party software
├── proc/         # Virtual filesystem for process/kernel info
├── sys/          # Virtual filesystem for hardware info
└── dev/          # Device files (sda, tty, null)

Practical Examples

# View the directory structure tree
ls -la /

# Check disk usage of major directories
du -sh /var /tmp /home /usr

# See what's in /proc (kernel and process info)
ls /proc/
cat /proc/cpuinfo
cat /proc/meminfo

# View mount points
df -h
mount | head -20

Why This Matters

When debugging a production server, knowing that logs live in /var/log, configs in /etc, and temp files in /tmp lets you navigate quickly. Misplacing files (e.g., logs in /home) causes confusion for the entire team.

File Types and the ls Command

File Types and the ls Command

Every file in Linux has a type. The ls -la output reveals it in the first character of the permissions string.

File Type Indicators

Character Type Example
- Regular file Text, binary, image
d Directory /etc/, /home/
l Symbolic link /usr/bin/python3 -> python3.11
c Character device /dev/tty, /dev/null
b Block device /dev/sda
p Named pipe (FIFO) Created with mkfifo
s Socket /var/run/mysqld/mysqld.sock

Reading ls -la Output

$ ls -la /etc/nginx/
drwxr-xr-x 5 root root 4096 Mar 10 14:23 .
-rw-r--r-- 1 root root 1077 Feb 18 09:45 nginx.conf
drwxr-xr-x 2 root root 4096 Mar 10 14:23 sites-enabled/

Breakdown: type(1) + permissions(9) + links + owner + group + size + date + name

The file Command

file inspects actual content, not just extensions:

$ file mystery_file
mystery_file: ELF 64-bit LSB executable, x86-64

$ file /usr/bin/python3
/usr/bin/python3: symbolic link to python3.11

$ file /dev/sda
/dev/sda: block special (8,0)

Glob Patterns (Wildcards)

# Match all .conf files in /etc
ls /etc/*.conf

# Match files starting with 'log'
ls /var/log/log*

# Match any single character
ls /etc/init.d/rs?

# Match any number of characters
ls /etc/ssh/sshd_config*

# Brace expansion
mkdir -p /tmp/{dev,staging,prod}
ls /tmp/{dev,staging,prod}

Practical Examples

# Find all symbolic links in /usr/bin
find /usr/bin -type l -ls 2>/dev/null | head -20

# List only directories
ls -d /etc/*/ | head -10

# Sort by modification time (newest first)
ls -lt /var/log/ | head -10

# Show file sizes in human-readable format
ls -lhS /var/log/

File Operations and Navigation

File Operations and Navigation

Master the essential commands for creating, copying, moving, and linking files.

Creating Files and Directories

# Create empty files
touch /tmp/newfile.txt

# Create directories (parent as needed)
mkdir -p /tmp/project/{src,bin,config}

# Create file with content
echo 'Hello World' > /tmp/greeting.txt

# Create multiple files
touch file{1..10}.txt

Copying and Moving

# Copy file (preserves permissions)
cp source.txt dest.txt

# Copy with verbose output
cp -v /etc/nginx/nginx.conf /tmp/nginx.conf.bak

# Copy directory recursively
cp -r /etc/nginx/ /tmp/nginx-backup/

# Preserve permissions, ownership, timestamps
cp -a /var/www/html/ /backup/html/

# Move/rename file
mv oldname.txt newname.txt
mv /tmp/file.txt /var/tmp/file.txt

# Move multiple files to a directory
mv *.log /var/log/archive/

Removing Files

# Remove file
rm file.txt

# Remove directory and contents
rm -rf /tmp/old-project/

# Remove empty directory
rmdir /tmp/empty-dir/

# Safe interactive removal
rm -i *.tmp

Symbolic Links vs Hard Links

# Symbolic (soft) link - points to path
ln -s /etc/nginx/nginx.conf /tmp/nginx-link
ls -la /tmp/nginx-link  # Shows -> /etc/nginx/nginx.conf

# Hard link - points to inode (same data)
ln /etc/hostname /tmp/hostname-hard
ls -li /etc/hostname /tmp/hostname-hard  # Same inode number

# Key difference: soft link breaks if original moves; hard link doesn't
# Soft links can cross filesystems; hard links cannot

Navigating with cd

# Go to home directory
cd ~  # or just cd

# Go to previous directory
cd -

# Go up one level
cd ..

# Go to root
cd /

# Go to another user's home
cd ~otheruser

Practical Exercise

# Create this structure and navigate it:
mkdir -p ~/project/{src/lib,tests,config/{dev,prod}}
touch ~/project/src/app.js ~/project/tests/test.js ~/project/config/dev/db.json

# Navigate to tests directory
cd ~/project/tests

# List files in config/prod from here
ls ../config/prod/

# Copy app.js to config as template
cp ../src/app.js ../config/dev/app.template.js

# Create a symlink to the config
cd ~/project
ln -s config/dev/dev-config.json ./dev-config.json
ls -la dev-config.json

Finding Files with find and locate

Finding Files with find and locate

The find Command

find recursively searches directories in real-time. It's powerful but can be slow on large filesystems.

# Find files by name
find / -name 'nginx.conf' 2>/dev/null

# Case-insensitive search
find /etc -iname '*.CONF'

# Find by type
find /var -type f -name '*.log'      # Files only
find /home -type d -name '.git'       # Directories only
find /dev -type b                     # Block devices

# Find by size
find / -size +100M                    # Larger than 100MB
find /tmp -size -1k                   # Smaller than 1KB

# Find by modification time
find /var/log -mtime -1               # Modified in last 24 hours
find /home -mmin -30                   # Modified in last 30 minutes

# Find by permissions
find / -perm 777 -type f              # World-writable files (security!)
find / -perm -4000 -type f            # SUID binaries

# Find and execute commands on results
find /tmp -name '*.log' -exec rm {} \;
find . -name '*.py' -exec grep -l 'import requests' {} \;

# Find and delete
find /var/tmp -type f -mtime +7 -delete

The locate Command

locate uses a pre-built database (/var/lib/mlocate/) for instant results. Update it with updatedb.

# Search instantly
locate nginx.conf

# Limit results
locate -l 10 '*.py'

# Update the database
sudo updatedb

# Case-insensitive
locate -i 'README'

Practical Examples

# Find all processes holding open files in /var/log
lsof +D /var/log 2>/dev/null | head -20

# Find files larger than 50MB and list them sorted
find / -type f -size +50M -exec ls -lh {} \; 2>/dev/null | sort -k5 -h

# Find all empty files and directories
find /tmp -empty

# Find files modified today and archive them
tar czf /backup/today.tar.gz $(find /var/log -type f -mtime -1)

# Security audit: find world-writable files outside /tmp
find / -path /proc -prune -o -path /sys -prune -o -perm -0002 -type f -print 2>/dev/null

Which and Type

# Find command location
which python3
# /usr/bin/python3

# Determine command type
type ls
# ls is aliased to 'ls --color=auto'

# Where is a binary on the PATH?
whereis nginx
# nginx: /usr/sbin/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz

Mounting Filesystems and /etc/fstab

Mounting Filesystems and /etc/fstab

Linux treats all filesystems as a single directory tree. You "attach" (mount) storage devices to mount points.

Basic Mount Commands

# View current mounts
mount | grep -E '^/dev'
df -hT    # Shows filesystem type and usage

# Mount a device
sudo mount /dev/sdb1 /mnt/data

# Mount with options
sudo mount -t ext4 -o rw,noatime /dev/sdb1 /mnt/data

# Unmount
sudo umount /mnt/data
sudo umount -l /mnt/data   # Lazy unmount (detaches now, cleans up later)

# Remount as read-only
sudo mount -o remount,ro /

The /etc/fstab File

/etc/fstab defines which filesystems mount automatically at boot:

# <device>                    <mount>   <type>  <options>              <dump> <fsck>
UUID=1234abcd-5678-efgh       /         ext4    defaults,noatime       0      1
UUID=abcd-1234                /boot     ext4    defaults               0      2
/dev/mapper/vg0-swap          none      swap    sw                     0      0
tmpfs                         /tmp      tmpfs   defaults,noexec,nosuid 0      0
/dev/sdb1                     /mnt/data ext4    defaults,nofail         0      2
//nas/share                   /mnt/nas  cifs    credentials=/etc/nascred,uid=1000 0 0

UUID vs Device Names

Device names (/dev/sdb1) can change between boots. UUIDs are stable:

# Find UUID of a partition
sudo blkid /dev/sdb1
# /dev/sdb1: UUID="1234abcd-5678-efgh" TYPE="ext4"

# Use UUID in fstab (copy-paste from blkid output)

Adding a New Disk

# Identify the disk
lsblk
sudo fdisk -l

# Partition the disk
sudo fdisk /dev/sdb
# n (new partition) -> p (primary) -> 1 -> default -> +50G -> w (write)

# Format the partition
sudo mkfs.ext4 /dev/sdb1

# Create mount point and mount
sudo mkdir -p /mnt/data
sudo mount /dev/sdb1 /mnt/data

# Add to fstab for persistence
echo 'UUID=$(sudo blkid -s UUID -o value /dev/sdb1) /mnt/data ext4 defaults 0 2' | sudo tee -a /etc/fstab

# Verify
sudo mount -a
mount | grep /mnt/data

Practical Tips

# Find which process is using a mounted filesystem (before unmount)
sudo lsof +f -- /mnt/data
sudo fuser -mv /mnt/data

# Check fstab without rebooting
sudo findmnt --verify

# View block devices with more detail
lsblk -f

Best Practices and Production Tips

Best Practices and Production Tips

Directory Organization Conventions

# Follow the FHS for your applications
/opt/myapp/              # Application binaries
/etc/myapp/              # Configuration files
/var/log/myapp/          # Log files
/var/lib/myapp/          # Persistent data
/tmp/myapp/              # Temporary runtime data

# Use consistent naming
mkdir -p /var/log/myapp/{access,error,audit}
mkdir -p /etc/myapp/{ssl,conf.d,env.d}

Security Checklist

# 1. Find and fix world-writable files
find / -path /proc -prune -o -path /sys -prune -o -perm -0002 -type f -print

# 2. Find files with no owner
find / -path /proc -prune -o -path /sys -prune -o -nouser -print

# 3. Check SUID/SGID binaries (limit these)
find /usr/bin /usr/sbin -perm /6000 -type f -ls

# 4. Protect sensitive config files
chmod 600 /etc/ssh/sshd_config
chmod 600 /etc/myapp/secrets.env
chown root:root /etc/myapp/secrets.env

# 5. Set proper permissions on web directories
chown -R www-data:www-data /var/www/html
chmod -R 750 /var/www/html

Disk Usage Monitoring Script

#!/bin/bash
THRESHOLD=80

df -h | awk 'NR>1 {print $5, $6}' | while read usage mount; do
    pct=${usage%?}
    if [ "$pct" -ge "$THRESHOLD" ]; then
        echo "WARNING: $mount is ${usage} full"
    fi
done

# Run via cron:
# 0 */6 * * * /usr/local/bin/disk_check.sh | mail -s 'Disk Alert' admin@example.com

Quick Reference Cheat Sheet

# Navigation
pwd                          # Print working directory
cd -                         # Previous directory
pushd /tmp && popd           # Directory stack

# File info
stat file.txt                # Detailed file metadata
file file.txt                # Determine file type
wc -l file.txt               # Count lines
diff file1 file2             # Compare files

# Disk usage
du -sh /var/*                # Size of each dir
df -h                        # Filesystem usage
ncdu /                       # Interactive disk usage tool

# Searching
grep -r 'pattern' /etc/     # Recursive grep
rg 'pattern' /etc/           # ripgrep (faster)
fd 'pattern' /etc/           # fd (user-friendly find)

Common Mistakes to Avoid

  • Never run rm -rf / — this destroys the entire filesystem
  • Always quote glob expansions in scripts: rm -- "$file" instead of rm $file
  • Use /tmp for temporary files, not random locations
  • Set noexec on /tmp to prevent executing uploaded binaries
  • Prefer UUIDs in fstab over device names which can change
  • Use find with -print0 and xargs -0 to handle filenames with spaces