Appearance
Finding Your Way Around Linux
You're following a tutorial that tells you to edit a config file at /etc/nginx/nginx.conf, and you type the path and hit enter, and the file isn't there. Or maybe it is, but when you try to save your changes, the editor says the file is read-only. Or you're trying to figure out where Docker stores its images because your disk is full, and ls ~ isn't showing you anything that explains where 40 gigabytes went.
Knowing individual commands like cd and ls gets you around your home directory. Understanding the Linux filesystem — the tree structure, what lives where, who owns what, and how to find things you didn't put there yourself — is what turns the terminal from a narrow hallway into a building you can walk through with your eyes closed. AI development pulls in packages, caches models, writes logs, and spins up containers, all of which land in different parts of the tree. If you can't find them, you can't clean them up, and eventually you run out of disk space or permissions and don't know why.
What you'll learn
- The Linux filesystem is a single tree rooted at
/— everything, including external drives and network mounts, lives somewhere under that one root - Permissions (read, write, execute for owner, group, and others) control who can do what to every file and directory
findandlocateare two different search strategies — one scans live, one queries an index — and you need bothduanddftell you where your disk space went, which is a question you'll ask every few weeks
The problem: you know the command but not where anything lives
On Windows, you have drive letters — C:, D:, and so on — and each one is its own root. Linux has one root, /, and everything hangs off it. A USB drive you plug in gets mounted somewhere like /media/usb. A network share appears at /mnt/nas. From the perspective of any program running on the system, it's all one tree.
Here are the directories you'll actually interact with:
| Directory | What's in it | Why you'll go there |
|---|---|---|
/home/yourname | Your personal files, projects, configs | This is your territory. Every project, every config file, every downloaded model lives here or under here |
/etc | System-wide configuration files | Editing /etc/hosts for local DNS, /etc/nginx/ for web server config, /etc/systemd/ for service definitions |
/var | Variable data: logs, databases, caches | /var/log/ is where system and service logs live. /var/lib/docker/ is where Docker stores images and containers — often the culprit when disk space vanishes |
/tmp | Temporary files, cleared on reboot | Scratch space. Good for one-off file operations you don't care about keeping |
/usr | Installed software, libraries, shared resources | /usr/bin/ is where most commands live. Python packages installed globally go under /usr/lib/python3/ |
/opt | Optional, manually installed software | Some third-party tools install here. If you install something from a tarball rather than a package manager, it might land in /opt |
The mental model to carry around: /home is yours, /etc is configuration you didn't write but sometimes need to edit, /var is data the system generates (and where runaway logs eat your disk), and everything else is the operating system doing its job.
Absolute vs. relative paths
An absolute path starts with / and describes the full route from the root of the tree: /home/yourname/projects/agent/main.py. No matter what directory you're currently in, that path always points to the same file.
A relative path starts from where you are right now. If you're in /home/yourname/projects, then agent/main.py and ./agent/main.py both resolve to the same absolute path as above. The dot means "this directory." Two dots means "up one level": from /home/yourname/projects, ../.. takes you to /home.
When to use which: absolute paths in scripts and config files (they don't break when the script is run from a different directory). Relative paths at the interactive prompt (less typing, and tab completion fills them in).
Options & when to use each
Here is how the different approaches for navigating and managing the Linux filesystem compare.
| Approach | Good for | Costs you | When to pick it |
|---|---|---|---|
| Terminal (cd, ls, find) | Speed, scripting, remote servers, bulk operations | Steeper learning curve — you need to know the commands | Any time you are doing more than a one-off drag-and-drop |
| GUI file manager | Casual browsing, previewing images, drag-and-drop moves | Cannot be scripted or chained with other tools | Quick visual tasks where you do not need to automate |
find | Searching by name, size, modification time, permissions — live scan of the actual filesystem | Slower on large directory trees because it reads the disk every time | One-off searches, or when you need filters locate does not support |
locate | Blazing fast name-only search using a pre-built index | Only searches by filename, index only updates once a day | Repeated searches for files you know the name of |
du+df | Finding disk hogs — what is eating your storage | Terminal-only, no pretty charts | "Why is my disk full?" — this is the answer |
Permissions: who can do what
Every file and directory has an owner, a group, and a set of permissions for three categories of users: the owner, members of the group, and everyone else. Each category gets three permissions: read (r), write (w), and execute (x).
bash
$ ls -la
drwxr-xr-x 2 alice devs 4096 Aug 1 10:00 src/
-rw-r--r-- 1 alice devs 1240 Aug 1 09:45 main.py
-rwxr-xr-x 1 alice devs 312 Aug 1 09:45 deploy.shLet's decode the first line: drwxr-xr-x. The d means it's a directory. Then three triplets:
rwx— owner (alice) can read, write, and execute (for a directory, "execute" means "can cd into it")r-x— group (devs) can read and execute, but not writer-x— everyone else can read and execute, but not write
For main.py: -rw-r--r--. The - means it's a regular file (not a directory). Owner can read and write. Group and others can only read. Nobody can execute it — and that's correct for a Python file you run with python main.py, because the executable is python, not main.py itself.
For deploy.sh: -rwxr-xr-x. Owner can read, write, and execute. Everyone else can read and execute. This is a shell script you want to be able to run directly with ./deploy.sh.
Changing permissions
bash
# Make a script executable by its owner
chmod u+x deploy.sh
# Remove write permission from group and others
chmod go-w config.yaml
# Set permissions numerically: owner=rwx, group=rx, others=nothing
chmod 750 private_script.shThe numeric mode maps each permission to a bit: read=4, write=2, execute=1. Add them up for each category. 750 means: owner gets 4+2+1=7 (rwx), group gets 4+1=5 (r-x), others get 0 (nothing).
Numeric mode is for setting all permissions at once. Symbolic mode (u+x, go-w) is for adjusting one category without touching the others. Use symbolic when you're adding or removing a single permission. Use numeric in scripts, where you want to be explicit about the exact final state.
Changing ownership
bash
# Change owner
sudo chown bob important_file.txt
# Change owner and group
sudo chown bob:devs important_file.txt
# Change recursively (entire directory tree)
sudo chown -R bob:devs ~/projects/shared_agent/You almost never need chown for files in your home directory — you already own everything you create there. chown is for files you've inherited from other users, or system files you've copied, or directories you want to share with someone else on the same machine.
Finding things: find vs. locate
These two commands solve the same problem — "where is that file?" — with completely different mechanics.
find | locate | |
|---|---|---|
| How it works | Walks the filesystem tree live, testing every file against your criteria | Queries a pre-built database that's updated once a day by updatedb |
| Speed | Slow on large directory trees | Nearly instant |
| Freshness | Always current — sees files created one second ago | Up to 24 hours stale — won't see files created since the last updatedb run |
| Power | Can filter by name, type, size, modification time, permissions, and execute commands on matches | Simple substring match on file paths |
| When to use | Searching a specific project directory, or when you need complex filters | "I know the filename contains 'cublas' and I have no idea where it is" |
find by example
bash
# All Python files modified in the last day
find ~/projects -name "*.py" -mtime -1
# Directories only, no files
find . -type d -name "logs"
# Files larger than 100MB (great for finding disk hogs)
find / -type f -size +100M 2>/dev/null
# Find and delete all .pyc files
find . -name "*.pyc" -deleteThe 2>/dev/null on that third example is important: running find on / will hit directories you don't have permission to read, and without it your terminal fills with "Permission denied" noise. The 2>/dev/null sends all those errors to the void so you only see the actual results.
locate by example
bash
# Find anything with "cuda" in the path
locate cuda
# Case-insensitive
locate -i Dockerfile
# Count matches
locate -c "*.so"
# If locate says "database not found," build it first
sudo updatedblocate is what you use when you know the name but not the location. A model weights file called pytorch_model.bin that you downloaded weeks ago? locate pytorch_model.bin finds it in under a second. find / -name "pytorch_model.bin" would take minutes.
Disk space: where did it all go?
Two commands answer the two disk questions you'll have.
df -h tells you how much space is free on each mounted filesystem. The -h flag makes the output human-readable (G for gigabytes instead of raw blocks).
bash
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p2 200G 140G 50G 74% /When your download fails with "no space left on device," df -h confirms it and shows you which filesystem is full.
du tells you how much space a directory and its contents are using. It's how you find the culprit.
bash
# How much space is my home directory using?
du -sh ~
# What are the 10 largest directories in my home?
du -h ~ | sort -hr | head -10
# What's eating space in /var?
sudo du -sh /var/* | sort -hr | head -10That last one is the debugging sequence for "my disk is full and I don't know why." Run it on /var first (Docker and logs love to hide there), then on ~ (model caches and Python environments), then on /tmp if you're still looking. The answer is almost always Docker images you forgot to prune, Python packages cached from old environments, or a log file that grew to 30GB because a process has been repeating the same error every millisecond for three weeks.
Build it: navigate, permission, find, and measure
Let's work through a realistic session that ties these tools together. You've just cloned an agent project and you want to understand its layout, fix a permission issue, and check that you have enough disk space.
Step 1: Get your bearings.
bash
cd ~/projects/customer-support-agent
pwd
ls -laLook at the directory structure. Which entries are directories, which are files? Who owns them? Are there any .env or .gitignore files that are hidden by default?
Step 2: Find every Python file and count them.
bash
find . -name "*.py" | wc -lThis tells you the scale of the project. A dozen Python files is a script. A thousand is a framework.
Step 3: Check if there's a config file you can't edit.
bash
ls -la config/If you see -r--r--r-- on a file you need to edit, you own it but can only read it. Fix it:
bash
chmod u+w config/settings.yamlIf you see a user other than your own name as the owner, you'll need sudo chown instead.
Step 4: Find the largest files in the project.
bash
find . -type f -size +10M -exec ls -lh {} \;Model weights, datasets, cached embeddings — AI projects accumulate large files. Knowing which ones exist and where they are saves you from surprise disk-full errors.
Step 5: Check overall disk health.
bash
df -h ~
du -sh ~/.cache/
du -sh ~/projects/If ~/.cache/ is 30GB, that's likely Hugging Face model downloads and pip caches. You can clean it with uv cache clean and pip cache purge when you need the space back.
What goes wrong
| Mistake | How you notice it | The fix |
|---|---|---|
chmod 777 on everything | You got a permission error, googled it, and applied the nuclear option: chmod -R 777 . | 777 means anyone on the system can read, write, and execute your files. For scripts, chmod u+x is almost always sufficient. For config files, chmod 600 keeps them private to you |
rm -rf /tmp/* thinking it's safe | /tmp is supposed to be temporary, right? But a running database or web server might have its socket file there | /tmp is fair game on a fresh system, but on a running development machine, check what's in there first with ls /tmp. Processes depend on files that happen to live in /tmp |
find with no path argument | find -name "*.py" works on some systems and fails on others — find expects a path as the first argument | Always include the starting path: find . -name "*.py". It's explicit, it's portable, and it prevents confusion |
Confusing du and df | df -h says the disk is 90% full, but du -sh / only reports 60GB on a 200GB drive | df measures filesystem-level allocation. If a file has been deleted but a process still has it open, the space isn't freed until that process closes it. Check with lsof | grep deleted to find these ghost files |
locate returns nothing for a file you know exists | You created the file five minutes ago, but locate queries yesterday's index | Run sudo updatedb to rebuild the index, or use find for freshly created files |
Confirm it worked
Open a terminal and work through these:
- Run
ls -la /and identify at least five of the top-level directories by what they contain - Navigate to a project directory, find all
.pyfiles modified in the last 7 days:find . -name "*.py" -mtime -7 - Create a test file:
echo "test" > /tmp/test_perms, thenchmod 000 /tmp/test_perms, try tocatit, observe the permission error, thenchmod 644 /tmp/test_permsand try again - Run
du -sh /var/lib/docker 2>/dev/nullto see how much space Docker is using (it might be zero if you don't have Docker installed — that's fine) - Use
locate bashrc(runsudo updatedbfirst if needed) to find every bashrc file on the system
If you can navigate to any directory on the system, read its permissions, and explain why you can or can't write to it, you've got this.
Next: Shell & Workspace Performance — aliases, lazy-loading, tmux, and making your terminal faster.