Skip to main content

Linux File System and Navigation — FHS, Paths, and Essential Commands

Master Linux filesystem hierarchy, absolute and relative paths, and the navigation commands used on every production server.

30 Terms

Every Linux server you will ever log into has the same directory structure. /etc always holds configuration. /var/log always holds logs. /proc always shows running processes. This predictability is not accidental — it comes from the Filesystem Hierarchy Standard (FHS), a specification that every major Linux distribution follows.

When a Hotstar engineer gets paged at 2 AM because the streaming API is returning errors, they do not hunt for log files. They go straight to /var/log/app/ because that is where logs live. They check /etc/nginx/ for configuration because that is where config lives. Understanding the FHS means any Linux server is immediately familiar.

Why It Matters

The Linux filesystem is the foundation underneath everything a DevOps engineer manages. Container images are Linux filesystems packaged differently. Kubernetes mounts volumes at specific paths inside containers. Ansible manages files at specific paths on remote hosts. CI/CD scripts read from and write to specific directories.

Misunderstanding paths is the source of a surprising number of production issues: a deployment script that works locally but fails in CI because relative paths resolve differently, a cron job that cannot find a binary because /usr/local/bin is not in cron's PATH, a Dockerfile that references the wrong path and silently copies nothing.

Core Principles

The Filesystem Hierarchy Standard — what lives where:

◈ DIAGRAM
/
+----+-- bin/ Essential binaries (ls, cp, mv, bash)
| +-- sbin/ System binaries (fdisk, iptables, sshd)
| +-- etc/ Configuration files — all of them
| +-- var/ Variable data (logs, databases, spool)
| | +-- log/ Application and system logs
| | +-- run/ PID files and runtime data
| +-- tmp/ Temporary files (cleared on reboot)
| +-- home/ User home directories
| +-- root/ Root user home directory
| +-- proc/ Virtual FS: live kernel and process data
| +-- sys/ Virtual FS: kernel hardware interface
| +-- dev/ Device files (disks, terminals, null)
| +-- mnt/ Manual mount points
| +-- media/ Auto-mount points (USB, CD)
| +-- opt/ Optional/third-party software
| +-- usr/ User programs
| | +-- bin/ Non-essential binaries
| | +-- lib/ Libraries
| | +-- local/ Locally installed software
| +-- lib/ Shared libraries
+----+-- boot/ Kernel and bootloader files

Absolute vs relative paths:

An absolute path starts from root (/) and is always unambiguous:

Bash
/etc/nginx/nginx.conf # always this exact file
/var/log/app/error.log # always this exact file
/home/deploy/.ssh/id_ed25519 # always this exact file

A relative path is resolved from the current working directory:

Bash
./deploy.sh # deploy.sh in current directory
../config/app.yaml # config/app.yaml one level up
logs/error.log # logs/error.log in current directory
Common Mistake

Relative paths in scripts, cron jobs, and systemd units almost always cause failures because the working directory is not what you expect. Always use absolute paths in automation.

The /proc filesystem — reading live kernel data:

/proc is not a real filesystem on disk. The kernel generates its contents on demand. Every running process has a directory /proc/PID/ containing live information:

Bash
cat /proc/1/cmdline # command that started PID 1
ls -la /proc/1234/fd/ # open file descriptors of PID 1234
cat /proc/meminfo # live memory statistics
cat /proc/cpuinfo # CPU information
cat /proc/sys/net/ipv4/ip_forward # current kernel parameter value

Step-by-Step Lab

Milestone 1 — Navigate the filesystem confidently

Bash
## Check where you are
pwd
## /home/youruser
## Go to root and explore
cd /
ls -la
## Go to etc and look at what is configured
cd /etc
ls -la | head -30
## Use absolute path from anywhere
ls -la /var/log/
## Go home quickly
cd ~ # or just: cd
pwd
## /home/youruser
## Go back to previous directory
cd /etc
cd -
## returns to /home/youruser

Milestone 2 — List files with useful flags

Bash
## Long format with human-readable sizes
ls -lh /var/log/
## Show hidden files (dotfiles)
ls -la ~
## .bashrc .ssh .profile are all hidden (start with .)
## Sort by modification time, newest first
ls -lt /var/log/
## Recursive listing
ls -R /etc/ssh/
## Show directories only
ls -d /etc/*/

Milestone 3 — Create, copy, move, and delete

Bash
## Create directories
mkdir -p /tmp/lab/configs/nginx # -p creates intermediate dirs
## Create files
touch /tmp/lab/app.log
touch /tmp/lab/{file1,file2,file3}.txt # brace expansion creates 3 files
## Copy
cp /etc/hosts /tmp/lab/hosts.backup
cp -r /etc/ssh/ /tmp/lab/ssh-backup/ # -r for directories
## Move (also used to rename)
mv /tmp/lab/file1.txt /tmp/lab/renamed.txt
## Remove
rm /tmp/lab/file2.txt
rm -r /tmp/lab/ssh-backup/ # -r for directories
## ALWAYS double-check before rm -rf
rm -rf /tmp/lab/ # removes everything, no recovery
Security

rm -rf with a variable (rm -rf $DIRNAME/) is extremely dangerous. If the variable is empty, this becomes rm -rf /. Always quote and validate variables before using them in delete commands.

Milestone 4 — Find files efficiently

Bash
## Find by name (case sensitive)
find /etc -name "nginx.conf"
## Find by name (case insensitive)
find /var/log -iname "*.log"
## Find files modified in the last 24 hours
find /var/log -mtime -1 -type f
## Find files larger than 100MB
find / -size +100M -type f 2>/dev/null
## Find files with specific permissions
find /home -name ".ssh" -type d -perm 700
## Find and execute a command on each result
find /tmp -name "*.tmp" -mtime +7 -delete
## Deletes .tmp files older than 7 days
## Faster search using index (update index first with: sudo updatedb)
locate nginx.conf
## Find which binary a command uses
which python3
## /usr/bin/python3
whereis nginx
## nginx: /usr/sbin/nginx /etc/nginx /usr/share/man/man8/nginx.8.gz

Milestone 5 — View file contents

Bash
## Print entire file
cat /etc/hosts
## View large files page by page (q to quit, /pattern to search)
less /var/log/syslog
## First 20 lines
head -n 20 /var/log/nginx/access.log
## Last 50 lines
tail -n 50 /var/log/nginx/error.log
## Follow a log file live (Ctrl+C to stop)
tail -f /var/log/app/application.log
## Follow and show last 100 lines first
tail -f -n 100 /var/log/app/application.log
## View file info
file /bin/bash # shows: ELF 64-bit executable
stat /etc/hosts # shows inode, size, timestamps, permissions

Milestone 6 — Check disk usage

Bash
## Disk space by filesystem
df -h
## Filesystem Size Used Avail Use% Mounted on
## /dev/xvda1 20G 12G 7.5G 62% /
## Disk usage of a directory
du -sh /var/log/
## 2.3G /var/log/
## Find the biggest directories
du -sh /var/* | sort -rh | head -10
## Find largest files in /var/log
find /var/log -type f -exec du -sh {} + | sort -rh | head -10

Milestone 7 — Work with links

Bash
## Create a symbolic link (soft link)
ln -s /opt/app/current/bin/app /usr/local/bin/app
## Now you can run 'app' from anywhere
## Update a symlink to point to new version
ln -sf /opt/app/v2.0/bin/app /usr/local/bin/app
## -f forces overwrite of existing link
## Create a hard link
ln /etc/hosts /tmp/hosts-hardlink
## Both point to same inode — same file, two names
## Read where a symlink points
readlink /usr/local/bin/app
## /opt/app/current/bin/app
## Find broken symlinks
find /usr/local/bin -xtype l
## Lists symlinks whose target does not exist

Common Mistakes

Mistake Problem Fix
Using relative paths in cron Cron runs from /, relative paths break Always use absolute paths
rm -rf with unquoted variable Variable empty = rm -rf / = disaster Quote vars, validate before delete
Confusing /tmp with persistent storage /tmp is cleared on reboot Use /var/ for persistent data
Editing files in /proc directly /proc is a virtual filesystem Use sysctl -w to change kernel params

Troubleshooting

Symptom First Command What to Look For
Disk full, cannot write files df -h Filesystem at 100% Use%
Cannot find a file find / -name filename 2>/dev/null Output shows path
Not sure which binary runs which commandname Full path to binary
File exists but app cannot read it ls -la filename Permission denied for relevant user
Symlink not working readlink -f symlinkname Target path does not exist
Tip

ls -lh (lowercase L) is the most useful listing command in production. It shows permissions, owner, size in human-readable format, and modification time — everything you need to diagnose a file issue.

Remember

/proc and /sys are virtual filesystems. They have no files on disk. The kernel generates their contents in memory on demand. Changes to /proc/sys/ via sysctl -w are lost on reboot — make permanent changes in /etc/sysctl.conf.

Resources

Explore More in Linux Fundamentals and File System

All 4 Topics

Frequently Asked Questions

Is Linux File System and Navigation — FHS, Paths, and Essential Commands free to learn on DevOps Network?

Yes - this topic, like everything on DevOps Network, is 100% free with no paywall or sign-up gate.

What does the Linux File System and Navigation — FHS, Paths, and Essential Commands topic cover?

Master Linux filesystem hierarchy, absolute and relative paths, and the navigation commands used on every production server.