Signal9Signal9 — home
online
all lessons

Files & Directories: Make, Copy, Move, Delete

Beginner35 min6 steps
What you'll learn
  • Create directories (including nested ones) and files with mkdir -p and touch
  • Copy files and whole directory trees with cp / cp -r, and know what -i protects you from
  • Move AND rename with mv — one command, two jobs — without clobbering things
  • Delete deliberately with rm and rmdir, understand -r, and treat -rf with earned respect
  • Act on many files at once with wildcards (*, ?, [..]) — and preview a glob before you trust it
  1. Making things: mkdir and touch

    Create directories (nested in one stroke) and empty files.

    Quick grounding before the commands. Everything on the system is one of two things: a file (content — text, an image, a program) or a directory (a container that holds files and other directories). That's the whole vocabulary. In the last lesson you learned to walk that tree of directories with pwd, ls, and cd; this lesson is about shaping it — creating, duplicating, relocating, and removing the files and directories in it. Same tree, now with tools to change it.

    It starts with just two creation commands that cover nearly everything:

    • mkdir name — make a directory right here.
    • mkdir -p a/b/c — make a whole nested chain in one command. -p (for "parents") creates every missing level along the way, and — handily — doesn't complain if some of them already exist.
    • touch name — create an empty file. (On a file that already exists, touch instead just updates its timestamp to now — which is the original reason for the name, and occasionally useful.)

    So standing up a project skeleton is just a couple of lines: mkdir -p project/src project/docs, then touch project/src/main.txt. Notice mkdir happily takes several directory names at once.

    mkdir -p workshop/tools/small && ls -R workshop
    workshop:
    tools
    
    workshop/tools:
    small
    
    workshop/tools/small:
    -p
    create parent directories as needed; stay quiet if they already exist
    -p built three nested levels — workshop, then tools inside it, then small — in a single command, and ls -R (recursive) walks the whole chain to prove it exists. Try that without -p and mkdir workshop/tools/small fails outright, because plain mkdir will only create the last directory and refuses when its parents are missing.

    Check yourself

    You need the nested path projects/2026/reports to exist, and none of it does yet. What's the one-command way?

  2. Copying: cp and cp -r

    Duplicate files and whole directory trees — without clobbering things by accident.

    cp (copy) makes a duplicate; the original always stays put, so after a cp there are two of the thing. The shapes you'll use:

    • cp source dest — copy a file. If dest is an existing directory, the copy lands inside it keeping its name; if dest is a filename, that becomes the copy's new name.
    • cp -r dir1 dir2 — copy a whole directory tree (recursive). Plain cp refuses directories on purpose — the -r is you saying "yes, everything inside too."
    • cp -i — interactive: ask before overwriting.

    That last one guards a real trap, so let's see it, not just read about it.

    Example — not runnable on your lab box

    cp notes.txt notes.bak && ls
    notes.bak  notes.txt
    -r
    recursive — copy a directory and everything inside it
    -i
    interactive — prompt before overwriting an existing destination
    -p
    preserve mode, ownership, and timestamps on the copy
    A plain file copy: notes.txt is untouched and notes.bak is a fresh duplicate of it. Because the destination was a filename (not a directory), the copy took that name. This is the everyday backup-before-I-edit move.

    Example — not runnable on your lab box

    mkdir -p archive && cp notes.txt archive && ls archive
    notes.txt
    This is the distinction that trips everyone up once: when the destination is an existing directory (archive), the copy lands inside it keeping its original name — so you get archive/notes.txt. Compare to the previous example, where the destination was a filename (notes.bak) and the copy took that name instead. Same command, two behaviours, decided entirely by whether the destination is a directory or a name.

    Check yourself

    cp refuses to copy your directory with 'omitting directory'. Which flag copies directories and everything inside them?

  3. Moving and renaming: mv is both

    Internalise that moving and renaming are the same operation.

    Here's a small realisation that makes mv (move) click: moving and renaming are the same thing. To the filesystem, a file's name is part of its path, so changing where it lives and changing what it's called are one operation. One command, three uses:

    • Move: mv report.txt archive/ — same name, new place.
    • Rename: mv report.txt report-final.txt — same place, new name.
    • Both at once: mv report.txt archive/report-final.txt.

    Unlike cp, after mv there's still only one file — it relocated, it wasn't duplicated. And the same silent-overwrite trap applies: mv a b replaces an existing b without asking, so mv -i is the careful version.

    touch draft.txt && mv draft.txt final.txt && ls
    final.txt
    -i
    interactive — prompt before overwriting an existing destination
    A rename is just mv with a new name as the destination. Notice draft.txt is gone from the listing entirely — the file itself became final.txt, contents completely untouched. Nothing was copied; the one file simply has a new name now.

    Check yourself

    What command renames meeting-notes.txt to 2026-07-notes.txt?

  4. Deleting: rm, rmdir, and the -rf conversation

    Delete on purpose, never by surprise.

    Before any syntax, the one fact that shapes everything about deletion: `rm` is permanent. There is no recycle bin, no undo, no "restore from trash." The moment rm returns, the file is genuinely gone. Internalise that and the careful habits below will feel natural rather than fussy.

    • rm file — delete a file.
    • rm -i file — ask "really?" first (training wheels worth wearing early).
    • rmdir dir — delete an empty directory only; it refuses if anything is inside. That refusal is a safety feature, not a limitation.
    • rm -r dir — delete a directory and everything inside it, recursively.
    • rm -rf dir — the same, plus -f (force), which suppresses errors and prompts.

    rm -rf has completely legitimate uses — you'll type it on throwaway build directories forever. What keeps it safe isn't avoiding it; it's one habit: read the line before you press Enter. Ask yourself: what exactly does this path match, and am I standing where I think I am (pwd)?

    rmdir workshop/tools/small && echo removed
    removed
    -r
    recursive — delete a directory and all its contents
    -i
    interactive — confirm each deletion
    -f
    force — suppress prompts and 'no such file' errors (use with care)
    rmdir removed small because it was empty. Try it on a directory with contents and it stops you cold — rmdir: failed to remove 'tools': Directory not empty. That error is rmdir protecting you: to delete a non-empty directory you must switch to rm -r and consciously accept that everything inside goes too.

    Check yourself

    rmdir refuses to delete your 'old-project' directory because it isn't empty. Which command deletes the directory AND its contents?

  5. Wildcards: acting on many files at once

    Understand globbing — and that the SHELL expands it before the command ever runs.

    Doing things one file at a time is fine for one file. Wildcards (also called globs) let you act on many at once by matching names against a pattern:

    • * — any number of any characters: *.log matches every name ending in .log.
    • ? — exactly one character: report-?.txt matches report-1.txt but not report-10.txt.
    • [..] — one character from a set: report-[12].txt matches report-1 and report-2 only.

    Now the single most important idea in this whole lesson, because it prevents disasters: *the shell expands the pattern first, then runs the command. When you type `rm .log, rm never sees *.log at all — the shell replaces it, so rm actually receives rm access.log error.log old.log`. The command has no idea a wildcard was ever involved.

    Example — not runnable on your lab box

    ls *.log
    access.log  error.log  install.log
    This is the dry run, and it's the professional's safety move. Because the shell expands *.log the same way for every command, this list is exactly what rm *.log would delete. If a name you didn't expect appears here — a file you meant to keep — you just caught it, for free, before anything was destroyed. Fix the pattern, then run the real command.

    Check yourself

    Before running 'rm *.bak', what command shows you exactly which files that pattern will match?

  6. Now do it — build, copy, prune

    Read it, then run it. Do a full create → copy → rename → preview → delete cycle in your live terminal.

    You have a real, throwaway sandbox to the right — the perfect place to make these commands muscle memory. Run this little lifecycle end to end and watch each step change what ls reports. If anything goes sideways, reset the lab and go again; that's exactly what it's for.

    mkdir -p lab/src && touch lab/src/a.txt lab/src/b.txt && ls lab/src
    Build a small tree and drop two empty files in it. You should see a.txt and b.txt. One mkdir -p and one touch (with two names) and the scaffold exists.
    cp -r lab lab-backup && ls
    Copy the whole lab tree to lab-backup — note the -r, because lab is a directory. Now there are two independent trees; editing one won't touch the other.
    mv lab/src/a.txt lab/src/first.txt && ls lab/src
    Rename a.txt to first.txt in place. a.txt disappears from the listing and first.txt takes its spot — same file, new name.
    ls lab/src/*.txt && rm lab/src/*.txt && ls lab/src
    The safe deletion pattern in one line: FIRST list what *.txt matches (preview), THEN delete it, THEN confirm the directory is empty. In real work you'd read that preview and pause before the rm — here you can watch the whole move at once.
Recap
  • mkdir -p builds whole nested paths in one command (and is safe to re-run); touch makes empty files.
  • cp duplicates (add -r for directories, -p to preserve metadata); mv relocates AND renames — the same operation to the filesystem.
  • cp and mv overwrite existing destinations silently — -i asks first; there is no undo for a clobbered file.
  • rm is permanent: no recycle bin. rmdir only deletes empty dirs (a feature); rm -r takes the whole tree; read the line — especially the spaces — before -rf.
  • Globs (*, ?, [..]) are expanded by the SHELL before the command runs — preview with ls/echo to see exactly what a pattern matches.
  • The four habits: preview globs, check destinations, respect rm, and pwd before anything destructive.
File-management quick reference
TaskCommand
Make a directory / nested pathmkdir name · mkdir -p a/b/c
Make an empty filetouch name
Copy a file / a directorycp src dest · cp -r dir dest
Ask before overwritingcp -i · mv -i
Move / renamemv thing place/ · mv old new
Delete a file / with confirmationrm file · rm -i file
Delete empty dir / whole treermdir dir · rm -r dir
Match many / one char / a set*.log · report-?.txt · file[12].txt
Preview what a glob matchesls pattern (or echo pattern)