Open the root of a Linux system and you get about twenty directories with terse names, several of which look like they do the same thing. /bin and /sbin and /usr/bin. /etc full of everything. /var, /opt, /srv, all apparently for “stuff”.

There is a logic to it, and once you have it you can guess where an unfamiliar file lives instead of searching for it. The organising idea is that directories are separated by who writes to them and how often — not by what kind of software they belong to.

One tree, not several drives

Linux has no drive letters. There is exactly one tree, starting at /, and every storage device appears somewhere inside it. A second hard disk is not “D:” — it is mounted at a directory such as /mnt/backup, and from then on it simply looks like part of the tree.

That means a path never tells you which physical device a file is on. df -h /var/log answers that question; the path alone does not. It also means “the disk is full” is an incomplete statement — which filesystem is full matters, because / and /home are often separate.

The map

DirectoryHoldsYou go here to
/etcSystem-wide configurationChange how anything is configured
/varData that changes: logs, caches, spools, databasesRead logs, find what filled the disk
/homeUsers’ personal filesEverything you own
/usrInstalled software and its dataRarely, directly
/tmpTemporary files, cleared on rebootScratch space
/optSelf-contained third-party softwareFind something installed outside the package manager
/srvData served by this machineSometimes web roots
/rootThe root user’s homeWhen logged in as root
/bootKernel and bootloaderBoot problems, or when it fills up
/devDevice filesReference disks and devices
/procLive kernel and process informationInspect a running system
/sysKernel and hardware interfacesTweak hardware settings
/mnt, /mediaMounted filesystemsReach a USB stick or extra disk
/lib, /bin, /sbinSymlinks into /usr on modern systemsNothing, deliberately

If you remember only three: /etc is configuration, /var is changing data, /home is yours. Those three cover the overwhelming majority of reasons you will ever navigate deliberately.

/etc — configuration

Every system-wide setting lives here, in plain text. That is one of the genuinely good design decisions in Unix: configuration is readable, greppable, diffable and version-controllable, with no binary registry.

PathWhat it configures
/etc/fstabWhich filesystems mount at boot
/etc/passwd, /etc/groupUsers and groups
/etc/shadowPassword hashes (root-only)
/etc/ssh/sshd_configThe SSH server
/etc/hostsLocal name overrides, before DNS
/etc/crontab, /etc/cron.d/System scheduled jobs
/etc/systemd/system/Your own service units
/etc/nginx/, /etc/apache2/Web servers

Two conventions are worth internalising. Many packages use a NAME.d/ directory alongside the main file — /etc/cron.d/, /etc/sudoers.d/, /etc/nginx/conf.d/ — where dropping in a new file adds configuration without editing anything shipped by the package. That is almost always the better way to make a change, because package updates will not fight you over it.

And when both /usr/lib/systemd/system/ and /etc/systemd/system/ contain the same unit name, /etc wins. The rule generalises: the distribution ships defaults under /usr, and your overrides go in /etc.

Because /etc is small and text-only, backing it up is cheap and repays itself the first time you rebuild a machine:

sudo tar czf etc-backup-$(date +%F).tar.gz /etc

/var — data that changes

Everything that grows while the machine runs. This is where disks fill up, and it is the first place to look when they do.

PathContains
/var/log/Log files — the first place to look when anything breaks
/var/lib/Application state: databases, package manager records, Docker images
/var/cache/Cached data, safe to delete
/var/spool/Queues: mail, print, cron jobs
/var/www/Website files, by convention on Debian family
/var/tmp/Temporary files that survive a reboot

The distinction between /var/lib and /var/cache matters more than it looks. /var/lib is real state — deleting /var/lib/mysql deletes your databases. /var/cache is regenerable and can be cleared freely. When you are hunting for space, that is the line between safe and catastrophic.

# The standard "what is eating my disk" sequence
df -h
sudo du -h --max-depth=1 /var | sort -h
sudo du -h --max-depth=1 /var/lib | sort -h

On a server the answer is almost always logs, a Docker image cache, or a database. Checking disk space covers the full method, including the inode trap where df -h shows free space but writes still fail.

/usr — installed software

/usr does not stand for “user” in any modern sense; read it as “Unix System Resources”. It holds everything the package manager installs: programs, libraries, documentation, icons.

PathContains
/usr/bin/Nearly every command you type
/usr/sbin/Administrative commands
/usr/lib/Shared libraries
/usr/share/Architecture-independent data: man pages, icons, timezone data
/usr/local/Software you installed yourself, outside the package manager

/usr/local is the one to remember. When you compile something from source or drop in a downloaded binary, it belongs in /usr/local/bin, not /usr/bin. The package manager owns /usr/bin and will happily overwrite what it finds there; /usr/local is reserved for you and survives updates.

Why /bin and /usr/bin both exist

Historically, /bin held the minimum needed to boot and repair a system when /usr was on a separate, possibly unmounted disk; /usr/bin held everything else. That distinction stopped being useful once initramfs took over early boot, so modern distributions have merged them — /bin is now a symlink to /usr/bin.

ls -ld /bin /sbin /lib
# lrwxrwxrwx ... /bin -> usr/bin

So do not agonise over the difference. Both paths reach the same file, and which tells you what you are actually running.

/home and dotfiles

Each user gets /home/username, referred to as ~. Root is the exception: its home is /root, deliberately outside /home so that root can still log in when /home lives on a disk that failed to mount.

Personal configuration lives in files beginning with a dot, which ls hides unless you pass -a:

PathWhat it is
~/.bashrcShell settings, aliases, prompt
~/.ssh/Your keys, known_hosts and client config
~/.config/Where most modern applications now store settings
~/.local/bin/Programs installed just for you
~/.cache/Per-user cache; safe to delete

The consequence worth knowing: backing up /home backs up your settings as well as your documents. Restore a home directory onto a fresh machine and your shell, keys and application preferences come back with it.

/proc and /sys — not really files

These two look like directories but exist only in memory. Reading a file in /proc asks the kernel a question and the answer is generated as you read it.

# CPU and memory, straight from the kernel
cat /proc/cpuinfo
cat /proc/meminfo

# How long the machine has been up, in seconds
cat /proc/uptime

# Everything about one running process
ls /proc/1481/
cat /proc/1481/cmdline
ls -l /proc/1481/cwd        # its working directory
ls -l /proc/1481/fd/        # every file it has open

Every numbered directory in /proc is a running process. This is where ps, top and free get their information — they are formatting what is already here. It is also genuinely useful: /proc/PID/fd/ shows exactly which files a stuck process has open, including a deleted file it is still holding, which is the classic explanation for disk space that does not come back after you delete something.

/sys is the same idea for hardware, and unlike /proc you can often write to it — screen brightness, CPU governor, and similar knobs live there.

Where should I put my own files?

WhatWhere
A script only you use~/.local/bin/
A script for everyone on the machine/usr/local/bin/
Software compiled from source/usr/local/
A vendor’s self-contained application/opt/vendorname/
Website files/var/www/ or /srv/
Your own service unit/etc/systemd/system/
Scratch, disposable at reboot/tmp/
An extra disk or USB stick/mnt/ or /media/

The one thing not to do is scatter files into / itself. It is technically allowed and it makes a machine unpleasant for everyone who touches it afterwards, yourself in six months included.

Finding things

# Which file runs when I type this command?
which nginx
command -v nginx

# Binary, source and man page in one
whereis nginx

# Which package installed this file?
dpkg -S /usr/sbin/nginx      # Debian, Ubuntu
rpm -qf /usr/sbin/nginx      # Fedora, RHEL
pacman -Qo /usr/bin/nginx    # Arch

# Every file a package installed
dpkg -L nginx
rpm -ql nginx

dpkg -L and rpm -ql are underused. When you have installed something and cannot find its configuration, listing the package’s files answers it immediately rather than guessing. For everything else there is find.

Quick reference

You wantLook in
To change a setting/etc/
To read a log/var/log/
To find what filled the disk/var/
Your own settings~/.config/, ~/.bashrc
A command’s actual locationwhich NAME
To install your own script/usr/local/bin/
Information about a running process/proc/PID/
Which filesystem a path is ondf -h /path

One refinement to “one tree”, now that you have the map. The tree is not a property of the machine — it is a property of each process, assembled from its own root, its own working directory and its own set of mounts. Two processes on one machine can read the same absolute path and get two different files, with neither of them misconfigured, and that is how containers and sandboxed systemd units work. How a Path Becomes a File follows a pathname from its first character to an open file in six stages: why PATH_MAX limits names rather than trees, the trailing slash that quietly defeats O_NOFOLLOW, why .. is a live pointer rather than a text edit, and why realpath cannot give you “the” path of a file — because files do not have one.

Related reading