Frontend Labs
⋯

Part 8 — Essential commands, in depth

Part 7 gave you the map; this part is the toolbox. These are the commands you'll type dozens of times a day, covered in enough depth that you understand what each one actually does to the filesystem underneath — not just which flags produce which output.

Chapter 26 — File and directory operations you'll use daily

In one sentence

cp, mv, rm, mkdir, and their close relatives look trivial and are genuinely, permanently dangerous when used carelessly — because Linux, by design, does not ask "are you sure?" before deleting your data.

Why this matters

More real data loss traces back to a mistyped rm than almost any other single command — knowing exactly what these commands do, and building the right habits, is part of using Linux professionally.

How it actually works

   cp source dest          copy a file
   cp -r sourcedir destdir copy a directory, RECURSIVELY (required for
                          directories -- plain `cp` refuses)
   mv source dest           move OR rename (same command; a rename is
                          just a move within the same directory --
                          Chapter 15's directory-entry model, again)
   rm file                  delete a file. NO confirmation, NO recycle
                          bin, NO undo, by default.
   rm -r directory           delete a directory and everything in it,
                          RECURSIVELY. Combined with -f (force, skip
                          confirmations) this is the single most
                          dangerous common command in daily use.
   mkdir -p a/b/c            create a/b/c, creating any missing parent
                          directories along the way (without -p, this
                          fails if `a` or `a/b` don't already exist)
   touch file                create an empty file, or update an
                          existing file's modification timestamp

Habits that prevent real disasters:

   # Always double-check a wildcard/variable BEFORE running rm with it
   echo rm -rf "$TARGET_DIR"/*      # print first, remove the `echo`
                                   # once you've confirmed it's correct

   # Prefer `rm -i` (interactive, asks per file) while learning
   alias rm='rm -i'                 # add to your shell config

   # For anything precious, copy before you touch it
   cp -a important_dir important_dir.bak

Real-world example

   In 2015, Valve's Steam client for Linux shipped an uninstall script
   containing (roughly) the command `rm -rf "$STEAMROOT/"*`. The bug,
   widely reported and acknowledged by Valve at the time: under certain
   conditions, the `$STEAMROOT` variable could end up EMPTY (unset or
   blank) before this line ran -- and an empty variable in that position
   silently turns the command into `rm -rf /*`, recursively deleting
   EVERYTHING the user running it had permission to delete, starting
   from the root of the filesystem. Multiple users reported losing their
   entire home directories as a result.
   THE LESSON, and it is a genuinely common real bug PATTERN, not just a
   one-off: a destructive command that depends on a VARIABLE being
   correctly set, with NO validation that the variable is actually
   non-empty before the destructive part runs, is a loaded gun. This is
   exactly why production-grade scripts (Chapter 39 covers this
   properly) check that critical variables are set before using them in
   anything destructive, and why the "echo it first" habit above is
   worth building now, permanently, before you're the one writing the
   script that runs as root against a production filesystem.

Try it yourself

# Safe practice, in your lab only
mkdir -p ~/lab/playground && cd ~/lab/playground
mkdir -p a/b/c
touch a/b/c/file1.txt a/b/file2.txt
cp -r a a_backup
mv a_backup a_renamed
find . -type f              # see the whole tree

# Deliberately reproduce (harmlessly) the class of bug from the
# real-world example -- see WHY checking your variable matters
TARGET=""                    # simulate the bug: empty variable
echo rm -rf "$TARGET"/*      # print it -- notice this would expand to
                             # `rm -rf /*` if TARGET is empty. NEVER
                             # remove the echo on a command like this
                             # without checking TARGET first.

rm -r a a_renamed            # clean up, safely, because we know exactly
                             # what's in this directory

Common mistakes

  • Running a destructive command with a variable, without checking it's set first. The Steam incident, exactly. Always validate, or echo first.
  • Assuming rm has an undo. On most Linux filesystems, by default, it doesn't — the data is gone (Chapter 15: the inode's link count hits zero, the space is freed). Backups are the only real undo.
  • Using mv across filesystems and assuming it's instant. Chapter 15 explained why a same-filesystem move is nearly free — a cross-filesystem move has to actually copy the data first, then delete the original, and can be interrupted partway, unlike a same-filesystem rename.

Check yourself

  1. Why does cp require -r for directories but rm doesn't (by default)?
  2. What specifically went wrong in the 2015 Steam Linux rm -rf incident?
  3. What habit would have prevented it, and why is "echo it first" a good general practice for destructive commands?

(Answers: Appendix E.)

Further reading

  • Reference: man 1 rm, man 1 cp, man 1 mv, man 1 mkdir.
  • History: search "Steam Linux rm -rf bug 2015" for Valve's own postmortem and community reports.
  • Practice: tldr rm / tldr cp (the tldr-pages project) for quick, example-driven command references.

Generated from real-life-os-guide.md · 8 Oct 2026 16:36