datarekha

Working with files & directories

How to create, copy, move, rename, and delete files and folders from the terminal — without losing work.

8 min read Beginner Command Line Lesson 3 of 14

What you'll learn

  • How to create files and directories with touch and mkdir
  • How to copy and move (or rename) files with cp and mv
  • How to delete files and directories safely — and why rm is permanent

Before you start

The last lesson left you able to tour the filesystem but never to change it — and ended on the catch that one of these reshaping commands has no undo and no “are you sure?” at all. Here are all five, that dangerous one included. Learn them and the terminal stops being a place you merely look at files and becomes a place you build with them.

Why bother learning file commands?

A graphical file manager is fine for one-off drags and drops. The terminal wins the moment you need to:

  • create a dozen nested directories in one shot,
  • rename a hundred files according to a pattern,
  • or move build artefacts as part of a repeatable script.

The commands below are POSIX-standard — they behave the same on Linux servers, macOS, and WSL, so learning them once pays off everywhere.

Creating directories: mkdir

mkdir reports
(no output — silence means success)

Create nested directories in one command with the -p flag (“parents”). Without -p, mkdir fails if an intermediate directory does not exist yet.

mkdir -p projects/2026/q2/data
(creates all four levels silently)

Flag at first use — -p: tells mkdir to create every missing parent directory along the path and to not complain if the directory already exists.

Creating empty files: touch

touch notes.txt
(no output)

touch has two behaviours:

  • If the file does not exist, it creates an empty file.
  • If the file already exists, it updates the file’s last-modified timestamp without changing its contents.

The timestamp behaviour is occasionally useful (some build tools check it), but creating empty placeholder files is the more common daily use.

Copying files and directories: cp

Copy a single file:

cp notes.txt notes-backup.txt
(no output)

Copy into a directory (the destination ends with an existing directory name):

cp notes.txt reports/

To copy a directory and everything inside it you need the recursive flag.

Flag at first use — -r (recursive): tells the command to descend into subdirectories and copy every file and folder it finds there.

cp -r projects/ projects-backup/
(no output — a full copy of the tree is made)

Moving and renaming: mv

mv is one command that does two jobs — they are the same underlying operation.

Move a file to a different directory:

mv notes.txt reports/notes.txt

Rename a file in place (just change the name, same directory):

mv notes-backup.txt notes-old.txt

Move and rename at the same time:

mv reports/notes.txt archive/meeting-notes-2026.txt

mv works on directories without any extra flags — no -r needed.

mv projects-backup/ old-projects/

If the destination already has a file of the same name, mv overwrites it silently by default. Use -i (interactive) to get a confirmation prompt instead:

mv -i notes.txt reports/notes.txt
overwrite reports/notes.txt? (y/n [n])

Deleting files and directories: rm and rmdir

Remove a single file:

rm notes-old.txt

Remove a directory only if it is already empty:

rmdir old-reports/

Remove a directory and all its contents recursively:

rm -r old-projects/

Filenames with spaces

Spaces in filenames break bare commands because the shell treats each word as a separate argument.

rm My Report.txt
rm: My: No such file or directory
rm: Report.txt: No such file or directory

Always quote names that contain spaces:

rm "My Report.txt"

Or escape the space with a backslash:

rm My\ Report.txt

Both forms work. Double quotes are usually easier to read.

Wildcards (globs) — a brief teaser

You can refer to groups of files using glob patterns instead of naming each file individually.

  • * matches any sequence of characters (including none).
  • ? matches exactly one character.
rm *.log
(removes every file ending in .log in the current directory)
cp report-?.txt archive/
(copies report-1.txt, report-2.txt … but not report-10.txt)

Globs are expanded by the shell before the command sees them — the command receives a plain list of filenames. A full lesson on glob patterns and quoting is in the pipeline; for now, just know they exist and that * is the one you will reach for most.

Quick reference

mkdir dir              create a directory
mkdir -p a/b/c         create nested directories
touch file.txt         create empty file (or update timestamp)
cp src dest            copy a file
cp -r srcdir/ destdir/ copy a directory recursively
mv src dest            move or rename
rm file.txt            delete a file (permanent)
rm -r dir/             delete a directory and its contents (permanent)
rm -rf dir/            same, with no prompts — use with extreme care
rmdir emptydir/        delete an empty directory
source.txt(original)copy.txtcp → keptdest.txtmv → gonedeleted.txtrm → ✗ no undo
cp keeps the source; mv removes it; rm has no undo.

In one breath

Five commands reshape the tree. mkdir makes a directory (-p builds every missing parent at once); touch makes an empty file (or bumps its timestamp). cp copies (-r for a whole directory) and leaves the source intact; mv both moves and renames in one operation, no -r needed for directories. rm deletes, and this is the one with no recycle bin: rm -r wipes a tree and rm -rf does it silently with no prompt — the classic footgun, especially with an unset variable. Reach for -i to be asked before each overwrite or delete, quote any filename containing spaces, and remember * and ? are globs the shell expands before the command ever sees them.

Practice

Before the quiz, plan and risk-check a real cleanup. You want to: create archive/2026/logs, move every .log file from the current directory into it, then remove the now-empty tmp/ folder. Write the three commands. Then spot the danger: if you had instead typed rm -rf $DIR/logs and $DIR happened to be unset, what does the command collapse to — and which one-line guard would have stopped it?

Quick check

0/3
Q1Which flag lets you create all intermediate parent directories in a single mkdir call?
Q2You run: mv report.txt archive/report.txt — but archive/ already contains a file named report.txt. What happens by default?
Q3A teammate hands you a script that ends with: rm -rf $BUILD_DIR. The script ran in the wrong directory and $BUILD_DIR was empty. What most likely happened?

A question to carry forward

You can now build, copy, move, and destroy files at will — but look at what you have been doing to them: shoving them around like sealed boxes. You moved config.yaml and deleted app.log without ever once seeing what was inside. That is fine until it is not: before you overwrite a config you want to glance at it; before you delete a log you want to read the last few lines that explain the crash; and some of these files are gigabytes, far too big to open in an editor. So how do you look inside a file from the terminal — peek at its head, tail its end, or page calmly through something enormous? That is the next lesson, and it closes out the basics.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Related lessons

Explore further

Cheat sheets
Skip to content