Phase 1 · FOUNDATIONS
Navigating & managing files — pwd, ls, cd, cp, mv, rm
By the end of today
- Move around any Linux tree using pwd, ls, cd, and tab-completion
- Copy, move, and delete files safely with cp, mv, and rm
- Know exactly why rm has no undo and no trash
Walking the tree, and moving what’s on it
Yesterday you learned that every file on a Linux box lives in one big tree. Today you learn to walk that tree and rearrange what’s on it — the six commands you’ll type more than any others for the rest of your career.
Start with the three that move you around. pwd — “print working directory” — answers “where am I?” It prints the absolute path from the root down to the directory you’re standing in. ls answers “what’s here?”; add -l for a long listing with sizes and permissions, and -a to reveal hidden dotfiles. cd — “change directory” — moves you: cd /etc jumps to an absolute path, cd logs steps into a child, and cd .. climbs to the parent.
That .. is worth pinning down. Every directory silently contains two entries: . means “this directory, right here”, and .. means “the parent”. So cd .. goes up one level, and ./deploy.sh means “run the deploy.sh in this exact directory” — you need the ./ because the shell doesn’t search your current directory for programs.
/home/pushkar <- pwd prints this absolute path
├── project/ <- `cd project` steps down into it
│ ├── . <- "here" = project/ itself
│ └── .. <- "up one" = back to /home/pushkar
└── notes.txt
One habit separates people who are fast in a terminal from people who fight it: tab-completion. Type the first few letters of a path and press Tab; the shell finishes it for you, or double-tap Tab to list the choices. It’s faster, and it kills typos before you hit Enter — which, as you’re about to see, matters a lot.
Now the three that move files. cp a b copies: you end up with two files. mv a b moves: the file leaves its old spot and appears at the new one — and because a rename is just a move to a new name, mv old.txt new.txt is also how you rename. rm b removes.
Here’s the part that catches everyone: rm has no undo and no trash. Delete something and it is gone — not in a recycle bin, not recoverable with Ctrl-Z. Add -r to delete a directory and everything inside it, -f to force past confirmation, and a single mistyped path can erase far more than you meant to.
Real world: Think of files as papers on a desk.
cpis running one through the photocopier — now you have two.mvis picking a page up and carrying it to another drawer — still one page, new home.rmis feeding it into a shredder with no bin underneath: the moment it’s through the blades, there is no getting it back.
That shredder is not hypothetical. In 2017 a GitLab engineer, untangling a late-night database problem, ran rm -rf against the live primary directory instead of the broken replica — and wiped roughly 300 GB of production data in seconds. Every one of their five backup and replication methods then turned out to be broken, and about six hours of data was gone for good. They live-streamed the recovery and published an unusually honest postmortem. The lesson every DevOps engineer takes from it: before you press Enter on rm, read the path out loud, and treat -rf the way you’d treat a live wire.
So today’s lab is where you build the muscle memory safely — on throwaway files, in your own home directory, where the only thing you can shred is practice.
Hands-On Lab
Budget about 25 minutes in your Ubuntu (WSL2) terminal. Work only inside a throwaway directory in your home folder so nothing you delete matters. Type each command yourself, read its output, then move on — building the muscle memory is the point.
# 1. Where does the session start? Always answer this first.
pwd
# Output:
# /home/pushkar
# 2. What's really here? -l = long view, -a = show hidden dotfiles.
ls -la
# Output — a fresh home holds only the three skeleton dotfiles:
# total 20
# drwxr-x--- 2 pushkar pushkar 4096 Jul 9 09:12 .
# drwxr-xr-x 3 root root 4096 Jul 9 09:12 ..
# -rw-r--r-- 1 pushkar pushkar 220 Jul 9 09:12 .bash_logout
# -rw-r--r-- 1 pushkar pushkar 3771 Jul 9 09:12 .bashrc
# -rw-r--r-- 1 pushkar pushkar 807 Jul 9 09:12 .profile
# 3. Make a sandbox and step into it. && runs cd only if mkdir succeeded.
mkdir mission-day3 && cd mission-day3
# (no output — a clean run is silent)
pwd
# Output — note you moved one level deeper:
# /home/pushkar/mission-day3
# 4. Create an empty file, then confirm it appeared.
touch a.txt
ls
# Output:
# a.txt
# 5. Copy it. cp leaves TWO files — original stays, duplicate appears.
cp a.txt b.txt
ls
# Output:
# a.txt b.txt
# 6. Move/rename b.txt to c.txt. mv leaves ONE file — b.txt is gone.
mv b.txt c.txt
ls
# Output:
# a.txt c.txt
# 7. Climb to the parent with `..`, then confirm you moved up.
cd ..
pwd
# Output:
# /home/pushkar
# 8. Step back in — type `mission-d` then press Tab to auto-complete the name.
cd mission-day3
pwd
# Output:
# /home/pushkar/mission-day3
# 9. Remove one file. Note: no "are you sure?" — it's just gone.
rm c.txt
ls
# Output:
# a.txt
# 10. Climb out and delete the whole sandbox. -r recurses into the directory.
cd .. && rm -r mission-day3
ls
# (no output — mission-day3 and a.txt are gone; only hidden dotfiles remain)
Before you close the terminal, read the outputs back in order and say what each proved: where you were, what a copy leaves behind, what a move leaves behind, and how quietly rm erased both the file and then the whole directory.
Common Errors & Fixes
Three mistakes almost everyone makes in their first hour with these commands. Learning to parse the message is the actual skill — read each one slowly.
Common error: Removing a file that isn’t there — a typo’d name or one you already deleted:
rm: cannot remove 'ghost.txt': No such file or directoryWhy:
rmis completely literal. It looked in the current directory for a file named exactlyghost.txt, found nothing, and reported it instead of guessing what you meant. A trailing typo or the wrong directory is usually the cause.Fix: Run
lsfirst to see the real names, and pressTabto auto-complete instead of typing the name by hand — the shell only completes names that actually exist, so a typo simply won’t complete.How you’d spot it in prod:
No such file or directoryin a deploy or cleanup script almost always means a path is relative when it should be absolute — the script ran from a different working directory than you assumed. Anchor the path (/var/www/app/…) rather than trusting where the job happens to start.
Common error: Copying a directory the same way you’d copy a file — forgetting that directories need recursion:
cp: -r not specified; omitting directory 'mission-day3'Why:
cpcopies a single file by default. Handed a directory, it refuses rather than silently copying only part of it — a directory has contents, and copying it means copying everything inside, which you have to ask for explicitly.Fix: Add
-r(recursive):cp -r mission-day3 backupcopies the directory and everything in it. The same-ris whyrm -ris needed to delete a directory — recursion is opt-in for both.How you’d spot it in prod: A backup or artifact-copy step that “succeeds” but produces an empty or missing target is often this —
cpprinted theomitting directoryline to stderr, the script ignored it, and the exit status got swallowed. Check that copy steps use-rand that the pipeline actually fails on non-zero exit.
Common error: Moving several files at once when the last argument isn’t an existing directory:
mv: target 'backup' is not a directoryWhy: With three or more arguments,
mvtreats the final one as the destination directory to drop everything into. Ifbackupdoesn’t exist (or is a plain file), there’s no folder to move them into, somvstops rather than overwrite one file with several.Fix: Create the directory first —
mkdir backup— thenmv a.txt c.txt backup/. For a straight rename, remembermvtakes exactly two arguments:mv old.txt new.txt.How you’d spot it in prod: A release script that moves build artifacts into a versioned folder breaks this way when the folder wasn’t created yet. Add
mkdir -pbefore the move so the destination is guaranteed to exist regardless of run order.
File Management Interview Questions
The four questions below come from real screening rounds, and this day’s answer bank renders right after this note. Cover each answer, say your own version out loud first, then compare — recalling before revealing is what makes it stick for interview day.
Go Deeper
Optional extras if you have ~30 more minutes today:
- 5 min — Run
man rmand read the-i,-I, and-rentries. Notice-Iprompts once before removing many files — a gentler safety net than-ifor bulk deletes. - 5 min — Install a real command-line trash bin:
sudo apt install trash-cli, then usetrash-put fileinstead ofrm. It’s the closest thing to a recycle bin on Linux — handy on your own box, though you won’t have it on most servers, which is exactly whyrmhabits matter. - 20 min — Read the File Directory Operations section of the Linux for DevOps guide for the wider set of file commands (
find,tar, archives) you’ll layer on top of today’s six.
What is the difference between cp and mv? Both
cp copies a file — you end up with two: the original stays put and a duplicate appears at the destination. mv moves it — the file leaves its old location and shows up at the new one, so there's only ever one copy. mv is also how you rename a file, because renaming is just moving it to a new name in the same directory: mv old.txt new.txt. One gotcha for both: if the destination already exists, they overwrite it silently, with no prompt. In scripts I add -i for an interactive confirm, or -n to never overwrite, so a deploy step can't clobber a file it shouldn't touch.
Why is rm -rf dangerous, and why is there no trash? Both
rm deletes immediately and permanently — there is no recycle bin on the command line, so the file's directory entry is gone the moment you press Enter. rm -rf compounds that: -r recurses into directories and -f forces past every 'are you sure?' prompt, so one wrong path can wipe a whole tree with no warning. The classic disaster is an empty variable — rm -rf $DIR/ becomes rm -rf / when $DIR is unset. That's why in production I never run it against a variable without checking the variable is set, I prefer explicit paths over wildcards, and I reach for -i or a trash tool on anything I'd hate to lose.
What is the difference between a relative and an absolute path? Both
An absolute path starts from the filesystem root with a leading slash — /etc/nginx/nginx.conf points to the same file no matter where you are. A relative path starts from your current directory and has no leading slash — nginx.conf or ../logs/error.log — so it means different things depending on where you're standing. Rule of thumb: use absolute paths anywhere the working directory isn't guaranteed — cron jobs, systemd units, deploy scripts — because those run from a directory you didn't choose. Use relative paths for quick interactive work and inside a project, where they keep commands short and stay correct if the whole project moves.
What do `.` and `..` mean in a path? Both
Every directory contains two hidden entries: `.` is the directory itself, and `..` is its parent. So cd .. walks one level up, and cd . goes nowhere — it just refers to where you already are. They matter most when you run a program that lives in the current directory: the shell won't search the current directory for executables, so you write ./deploy.sh to say 'run the deploy.sh right here', not some deploy.sh on your PATH. You'll also see `..` in relative paths like ../config to reach a sibling directory, and in copies like cp -r ./src .. to write into the parent.
Mark Day 3 complete
You can move files around now — tomorrow you crack them open to read and edit with cat, less, nano, and just-enough vim.
Stuck on today’s lab? Ask in Mission 90 Q&A