Working with files & directories
How to create, copy, move, rename, and delete files and folders from the terminal — without losing work.
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
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