Linux File System Explained — Structure, Directories and How It All Works
Every time you run a command in a Linux terminal, copy a file, or install software, the Linux file system is quietly doing the heavy lifting behind the scenes. It's the invisible backbone of every Linux server, every Docker container, every cloud VM you'll ever touch as a DevOps engineer. Understanding it isn't optional — it's the foundation everything else is built on.
Before Linux, different operating systems stored files in completely different ways with no agreed standard. This made software hard to port, hard to maintain, and easy to break. Linux solved this with the Filesystem Hierarchy Standard (FHS) — a clearly defined blueprint that says exactly where system files live, where user data goes, where temporary files are kept, and why. Every Linux distro you'll ever meet — Ubuntu, CentOS, Debian, Alpine — follows this same blueprint.
By the end of this article you'll be able to navigate any Linux system with confidence, explain what every major directory is for, read file paths without guessing, and answer the Linux file system questions that actually come up in DevOps interviews. No previous Linux experience needed — we're starting from zero.
The Root of Everything — How the Linux File System Tree Works
In Windows you might be used to drives like C:\ and D:\. Linux throws that idea out entirely. Instead, everything — and we mean everything — lives under one single top-level directory called root, written as just a forward slash: /
Think of it like a family tree. The great-grandparent at the very top is /. Every single file, folder, device, and process on the system hangs off a branch below it. There is no 'outside' of this tree.
This matters because it makes the system predictable. No matter which Linux machine you sit down at — a tiny Raspberry Pi or a massive cloud server — the layout is the same. /etc always holds configuration files. /var always holds variable data like logs. /home always holds user files. Once you learn the map, you can navigate any Linux system on earth.
The technical term for this design is a hierarchical file system, but honestly just think of it as a tree of folders with / at the very top. Every path you type starts from there — either absolutely (starting with /) or relatively (starting from wherever you currently are).
#!/bin/bash # Let's explore the very top of the Linux file system tree # The 'ls' command lists what's inside a directory # The '/' argument tells it to look at the root directory ls / # Now let's see it as a proper tree structure # The 'tree' command shows directories visually (install with: sudo apt install tree) # We use -L 1 to only go ONE level deep — otherwise it prints thousands of lines tree -L 1 / # Let's also see our current location in the file system # 'pwd' stands for Print Working Directory — it tells you exactly where you are pwd
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
# Output of: tree -L 1 /
/
├── bin
├── boot
├── dev
├── etc
├── home
├── lib
├── lib64
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin
├── srv
├── sys
├── tmp
├── usr
└── var
20 directories, 0 files
# Output of: pwd
/home/youruser
Every Major Directory Explained — What Lives Where and Why
Here's where most beginner guides fail you — they list directories like a dictionary with no story. Let's actually understand each one by thinking about WHO put files there and WHY.
/bin holds essential binaries (programs) that every user needs even during early system startup — things like ls, cp, mv, and cat. Think of it as the essential tools drawer in your kitchen.
/etc (pronounced 'et-see') is the system's configuration cabinet. Every time you install software and it has settings, those settings live in /etc. Apache web server config? /etc/apache2. SSH settings? /etc/ssh/sshd_config. User accounts list? /etc/passwd.
/home is where real people live. Every user on the system gets their own sub-folder here — /home/alice, /home/bob. It's where your documents, downloads, and personal configs go.
/var holds variable data — stuff that changes constantly while the system runs. Logs are the big one: /var/log. Package manager data, mail spools, and database files live here too.
/tmp is a scratch pad. Files here are wiped on reboot. Never store anything important here.
/proc and /sys are virtual directories — they don't contain real files on disk. They're a live window into the Linux kernel. Reading a file in /proc actually asks the kernel for current system information in real time.
#!/bin/bash # Let's visit the most important directories and see what's actually in them echo "=== Binaries in /bin ===" # List a sample of the programs available to all users ls /bin | head -20 # 'head -20' shows just the first 20 results echo "" echo "=== Configuration files in /etc ===" # See what software has configuration here ls /etc | head -20 echo "" echo "=== User home directories in /home ===" # Each user on the system has a folder here ls /home echo "" echo "=== Recent system log entries from /var/log ===" # The system constantly writes logs here — let's see the last 5 lines of the system log tail -5 /var/log/syslog # On CentOS/RHEL use: /var/log/messages echo "" echo "=== Live kernel data from /proc ===" # This is NOT a real file — the kernel generates it on the fly when you read it # It shows the current uptime of the system (how long it's been running) cat /proc/uptime # Two numbers: seconds uptime, seconds idle time echo "" echo "=== CPU info straight from the kernel ===" # Again, not a real file — the kernel answers this query live cat /proc/cpuinfo | grep 'model name' | head -2
bash
cat
chmod
chown
cp
date
dd
df
dir
echo
false
grep
gzip
hostname
kill
ln
ls
mkdir
mv
nano
=== Configuration files in /etc ===
apt
bash.bashrc
cron.d
crontab
default
environment
fstab
group
hostname
hosts
init.d
issue
kernelcrash
ldap
logrotate.conf
logrotate.d
lsb-release
mtab
network
nginx
=== User home directories in /home ===
alice bob deploy
=== Recent system log entries from /var/log ===
Jun 12 14:22:01 myserver CRON[3421]: (root) CMD (run-parts /etc/cron.hourly)
Jun 12 14:22:01 myserver CRON[3420]: (root) SESSION (open)
Jun 12 14:22:01 myserver CRON[3420]: (root) SESSION (close)
Jun 12 14:25:01 myserver CRON[3502]: (root) CMD (test -x /usr/sbin/anacron)
Jun 12 14:30:01 myserver CRON[3611]: (root) CMD (run-parts /etc/cron.hourly)
=== Live kernel data from /proc ==="
183426.52 712930.18
=== CPU info straight from the kernel ===
model name : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
model name : Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
Absolute vs Relative Paths — The GPS Coordinates of Your File System
Now that you know the layout of the city, you need to know how to give directions in it. In Linux, every file has an address called a path. There are two ways to express that address, and understanding both will save you from a lot of confusion.
An absolute path starts with / and gives the full address from the root of the system, no matter where you currently are. It's like a GPS coordinate — completely unambiguous. /home/alice/documents/report.txt will always find that file, whether you're in /tmp, /etc, or anywhere else.
A relative path starts from wherever you currently are (your working directory). If you're already inside /home/alice, you can just say documents/report.txt and Linux figures out the rest. Two dots (..) means 'go up one level'. One dot (.) means 'right here'.
Why does this matter? When you write shell scripts or Dockerfiles, using relative paths can cause scripts to break when run from a different directory. Absolute paths are bulletproof. In contrast, relative paths are faster to type interactively. Knowing which to use and when is a skill that separates competent Linux users from beginners.
#!/bin/bash # Demonstrating absolute vs relative paths with a practical example # We'll create a small directory structure, then navigate it both ways # First, create a demo folder structure in /tmp (safe scratch space) mkdir -p /tmp/demo_project/src/utils # -p creates all parent folders at once mkdir -p /tmp/demo_project/config touch /tmp/demo_project/src/main.py touch /tmp/demo_project/config/settings.yml echo "=== Directory structure created ===" tree /tmp/demo_project echo "" echo "=== Navigating with ABSOLUTE paths ===" # cd changes your current directory # Absolute path — starts with / — works from ANYWHERE cd /tmp/demo_project/src pwd # Confirm where we are # List the config folder using its full absolute address ls /tmp/demo_project/config # Works no matter where we are echo "" echo "=== Navigating with RELATIVE paths ===" # We're currently in /tmp/demo_project/src # Go UP one level with .. then into config cd ../config # .. means 'one folder up', so this goes to /tmp/demo_project/config pwd # The single dot (.) means 'current directory' ls . # Same as: ls /tmp/demo_project/config echo "" echo "=== Using ~ as a shortcut for your home directory ===" # The tilde character is a special shortcut — always means your home folder echo "My home directory is: ~" cd ~ pwd # Will show /home/yourusername # Clean up our demo rm -rf /tmp/demo_project echo "Demo cleaned up."
/tmp/demo_project
├── config
│ └── settings.yml
└── src
├── main.py
└── utils
3 directories, 2 files
=== Navigating with ABSOLUTE paths ===
/tmp/demo_project/src
settings.yml
=== Navigating with RELATIVE paths ===
/tmp/demo_project/config
settings.yml
=== Using ~ as a shortcut for your home directory ===
My home directory is: ~
/home/alice
Demo cleaned up.
File Permissions — Who's Allowed to Touch What
The Linux file system isn't just about WHERE files are stored — it also controls WHO can access them. This is the permission system, and it's one of the most important security concepts in Linux.
Every file and directory has three types of permission: read (r), write (w), and execute (x). And those permissions are set separately for three groups of people: the owner (the user who created the file), the group (a team of users), and everyone else (the world).
When you run ls -l, you see a string like -rwxr-xr-- at the start of each line. That's 10 characters. The first is the file type (- for file, d for directory). The next three are owner permissions. The next three are group permissions. The last three are everyone else's permissions.
Permissions are also expressed as numbers — this is called octal notation. r=4, w=2, x=1. Add them together for each group. So rwx = 7, r-x = 5, r-- = 4. A permission of 755 means the owner can do everything (7), and everyone else can read and execute but not write (5). This comes up constantly in DevOps when deploying files or running scripts.
#!/bin/bash # Hands-on demo of Linux file permissions # We'll create files, read their permissions, and change them # Create a sample script file cat > /tmp/deploy_script.sh << 'EOF' #!/bin/bash echo "Deploying application..." EOF echo "=== Default permissions after creation ===" # ls -l shows the long format with permissions ls -l /tmp/deploy_script.sh # You'll see something like: -rw-r--r-- 1 alice alice 42 Jun 12 14:00 deploy_script.sh # That means: owner can read+write, group can read, everyone can read echo "" echo "=== Trying to EXECUTE without execute permission ===" /tmp/deploy_script.sh # This will fail — no execute permission yet! echo "" echo "=== Adding execute permission with chmod ===" # chmod changes permissions # 755 = rwxr-xr-x: owner has full access, group and others can read+execute chmod 755 /tmp/deploy_script.sh ls -l /tmp/deploy_script.sh # Confirm the change echo "" echo "=== Now we can execute it ===" /tmp/deploy_script.sh # Works now! echo "" echo "=== Making a file secret — only the owner can read it ===" echo "db_password=SuperSecret123" > /tmp/database.conf chmod 600 /tmp/database.conf # rw------- : only owner can read or write ls -l /tmp/database.conf echo "" echo "=== Breaking down what we see in ls -l ===" # Let's use stat for a crystal-clear view stat /tmp/deploy_script.sh # Clean up rm /tmp/deploy_script.sh /tmp/database.conf
-rw-r--r-- 1 alice alice 42 Jun 12 14:00 /tmp/deploy_script.sh
=== Trying to EXECUTE without execute permission ===
bash: /tmp/deploy_script.sh: Permission denied
=== Adding execute permission with chmod ===
-rwxr-xr-x 1 alice alice 42 Jun 12 14:00 /tmp/deploy_script.sh
=== Now we can execute it ===
Deploying application...
=== Making a file secret — only the owner can read it ===
-rw------- 1 alice alice 26 Jun 12 14:00 /tmp/database.conf
=== Breaking down what we see in ls -l ===
File: /tmp/deploy_script.sh
Size: 42 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1572867 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 1000/ alice) Gid: ( 1000/ alice)
Access: 2024-06-12 14:00:01.000000000 +0000
Modify: 2024-06-12 14:00:01.000000000 +0000
Change: 2024-06-12 14:00:05.000000000 +0000
Birth: -
| Directory | Purpose | Typical Contents | Who Writes Here |
|---|---|---|---|
| /bin | Essential user binaries | ls, cp, mv, cat, bash | OS installer |
| /etc | System-wide configuration | nginx.conf, sshd_config, fstab | Admins & package managers |
| /home | User personal files | Documents, dotfiles, downloads | Individual users |
| /var | Variable runtime data | Logs, caches, mail spools, databases | Running services & OS |
| /tmp | Temporary scratch space | Partial downloads, build artifacts | Any process — wiped on reboot |
| /usr | User programs & libraries | Most installed software and libs | Package managers |
| /opt | Optional third-party software | Manually installed apps, vendors | Admins & vendors |
| /proc | Live kernel data (virtual) | CPU info, process info, uptime | Linux kernel (no disk space used) |
| /dev | Device files | sda (disk), tty (terminal), null, zero | Linux kernel |
| /boot | Boot files | Kernel image, GRUB bootloader config | OS installer & kernel updates |
🎯 Key Takeaways
- Everything in Linux lives under a single root directory '/' — there are no separate drives like Windows C:\ or D:\, just one connected tree of directories branching from that single point.
- The directory layout is standardised by the Filesystem Hierarchy Standard (FHS) — /etc is always config, /var is always runtime data, /home is always user files — so once you learn the map, every Linux system on earth makes sense.
- Absolute paths (starting with /) are bulletproof and always work regardless of where you are in the file system — always use them in scripts and cron jobs to avoid hard-to-debug failures.
- File permissions control read (r=4), write (w=2), and execute (x=1) separately for the owner, group, and everyone else — understanding octal notation like 755 and 600 is essential for secure DevOps work.
⚠ Common Mistakes to Avoid
- ✕Mistake 1: Confusing /root with / — Beginners type 'cd root' or think the admin home folder is the top of the file system. Symptom: you end up in /home/youruser/root (which doesn't exist) or get 'No such file or directory'. Fix: '/' is the top of the tree. '/root' (with a leading slash) is the home directory of the root user. Always use 'cd /' to go to the absolute top.
- ✕Mistake 2: Using relative paths in cron jobs or scripts — Your script works perfectly when you run it manually but silently fails in a cron job. Symptom: cron runs the script but can't find config files or output goes to the wrong place. Fix: cron jobs run with / as the working directory. Always use absolute paths in scripts that run automatically, or set the working directory explicitly at the top of the script with 'cd /path/to/your/app || exit 1'.
- ✕Mistake 3: Running chmod 777 to 'fix' permission errors — It works, so it seems fine. The symptom is that your permission denied error goes away. The hidden problem: you've now made that file writable by every process and user on the system, including any attacker who gains the lowest-privilege access. Fix: think about WHO actually needs access. A web server config that nginx reads should be 644 (owner writes, everyone reads). A credentials file should be 600 (only the owner reads or writes it). Start restrictive and loosen only as needed.
Interview Questions on This Topic
- QWalk me through the Linux file system hierarchy. What's the difference between /bin, /usr/bin, and /usr/local/bin — and why do all three exist?
- QWhat's an inode in the Linux file system, and why would you care if a disk shows space available but you still can't create new files?
- QA junior dev on your team ran 'chmod 777 -R /var/www/html' to fix a web server permission error. What's the problem with this, and how would you fix it properly?
Frequently Asked Questions
What is the Linux file system and how is it different from Windows?
The Linux file system is a single unified directory tree that starts at a root directory called /. Unlike Windows which uses separate drive letters (C:\, D:\), Linux mounts everything — including external drives and network shares — as subdirectories within that one tree. This makes the system layout consistent and predictable across all Linux machines.
What is /etc in Linux and what does it stand for?
The /etc directory holds system-wide configuration files. Historically the name stood for 'et cetera' (miscellaneous), but today it's best understood as 'Editable Text Configuration'. Nearly every program you install on Linux stores its settings as text files in /etc — for example, /etc/nginx/nginx.conf for the Nginx web server or /etc/ssh/sshd_config for SSH settings.
Why can't I find files in /proc on disk — are they real files?
/proc is a virtual filesystem, which means the files you see there don't actually exist on your hard drive and take up zero disk space. When you read a file like /proc/cpuinfo or /proc/uptime, the Linux kernel generates that information on the fly and hands it to you as if it were a file. It's one of Linux's most elegant tricks — you can query live kernel data using standard file-reading tools like cat.
Written and reviewed by senior developers with real-world experience across enterprise, startup and open-source projects. Every article on TheCodeForge is written to be clear, accurate and genuinely useful — not just SEO filler.