open atlas
↑ Back to track
Command line CLI · 02 · 02

Making, copying, moving, and deleting

mkdir creates directories, cp copies files or directory trees, mv moves or renames them, rm deletes them permanently — there is no Trash. The rm -rf combination is the most dangerous command beginners encounter: it silently destroys entire directory trees with no undo.

CLI Foundations ◷ 22 min
Level
FoundationsJuniorMiddleSenior

Navigating the filesystem is only half the story. Real work means creating project directories, copying config files, renaming outputs, and cleaning up temporary files. Four commands cover all of this: mkdir, cp, mv, and rm. One of them — rm with two flags — is the most destructive command a beginner will encounter. You need all four, and you need to know which one has no undo.

By the end of this lesson you will be able to create directory trees, copy files and folders, rename or relocate anything on the filesystem, and delete files — while understanding exactly why rm -rf deserves special caution.

Goal

After this lesson you can use mkdir (with -p for nested directories), cp (with -r for directories), mv (for both moving and renaming), and rm (with -r and -f and a clear understanding of the risk). You can predict the outcome of each command before running it.

1

mkdir creates a directory. Pass one or more names and it creates them in the current directory (or at the path you give):

mkdir projects
mkdir /tmp/sandbox

The -p flag (parents) creates all intermediate directories at once and does not error if they already exist. Without -p, creating a/b/c when a/b does not yet exist fails:

# fails if projects/ does not yet exist
mkdir projects/backend/src

# succeeds: creates projects/, projects/backend/, projects/backend/src/
mkdir -p projects/backend/src

-p is the flag you will use almost every time you create nested paths in scripts.

2

cp copies files. The syntax is cp SOURCE DEST:

cp notes.txt notes-backup.txt        # copy within same directory
cp notes.txt /tmp/notes.txt          # copy to a different directory
cp /etc/hosts ~/hosts-backup         # copy system file to home

If DEST is an existing directory rather than a file path, cp places the copy inside that directory keeping the original filename:

cp notes.txt backups/    # creates backups/notes.txt

To copy a directory and everything inside it, add -r (recursive):

cp -r projects/ projects-backup/

Without -r, trying to copy a directory produces an error: cp: omitting directory 'projects/'.

3

mv moves or renames. The syntax is mv SOURCE DEST. When DEST is in the same directory, it is a rename. When DEST is a different directory, it is a move. When DEST is a different directory and filename, it is both:

mv draft.txt final.txt               # rename in place
mv final.txt ~/documents/            # move to documents/
mv draft.txt ~/documents/final.txt   # move and rename

Unlike cp, mv does not leave the original behind. On the same filesystem, mv is instantaneous — it just updates the directory entry (no data is copied). Across filesystems, mv copies then deletes.

4

rm deletes files permanently — there is no Trash. Unlike a graphical file manager, rm does not send files to a recoverable location. Once gone, they are gone (unless you have a backup or forensic tools):

rm old-log.txt
rm /tmp/scratch.txt

To delete a directory and everything inside it, add -r (recursive). Add -f (force) to suppress confirmation prompts and ignore missing files:

rm -r old-project/
rm -rf temp/

The combination -rf is powerful and permanent. See the Inset below.

Worked example

Setting up a project scaffold from scratch.

# 1. Create the directory tree in one shot
mkdir -p myapp/src myapp/tests myapp/docs
# 2. Verify
ls myapp/
docs  src  tests
# 3. Copy a template config file into the project
cp /etc/hostname myapp/docs/hostname-reference.txt
# 4. Rename the config to something meaningful
mv myapp/docs/hostname-reference.txt myapp/docs/server-info.txt
# 5. Clean up a stale scratch file
rm myapp/docs/server-info.txt

Each step is deterministic: mkdir -p never errors if the tree already exists, cp always leaves the source intact, mv removes the source, and rm removes the target permanently.

Common mistake

rm -rf is irreversible and ignores all safeguards.

-r means “recurse into every subdirectory”. -f means “force: suppress all prompts and ignore missing files”. Together they will silently delete an entire directory tree — including symlinks pointing outside the tree, and anything the current user has write permission on.

The classic disaster:

# Intended: remove the 'dist' build directory
rm -rf dist/

# Typo with a space: removes 'dist' AND everything else in /
rm -rf dist /
#            ^ space before /  →  two arguments: "dist" and "/"

A space between dist and / turns one argument into two. The shell sees rm -rf dist / — delete dist, then delete / (the filesystem root). On a system without protection this destroys the OS.

Rules to internalize:

  1. Always echo the path before rm -rf if you are uncertain: echo rm -rf "$DIR".
  2. Define DIR in a variable and check it is not empty before use.
  3. Prefer rm -ri (interactive) when learning — it asks before each deletion.
  4. Never run rm -rf as root unless you have verified every argument.
Why this works

On macOS, cp and mv work identically. rm also has no Trash — the same risk applies. One difference: macOS cp does not support -r for recursive copy in exactly the same way as GNU cp; use -R (capital R) on macOS when -r is ambiguous. In scripts targeting both systems, -R is the safe choice.

Check yourself
Quiz

You run: cp report.pdf archive/. The directory archive/ already exists and is empty. What is the result?

Recap

mkdir creates directories; add -p to create nested paths without errors. cp SOURCE DEST copies files and, with -r, entire directory trees — the source is always preserved. mv SOURCE DEST moves or renames; the source disappears, and on the same filesystem the operation is instantaneous. rm permanently deletes files — there is no Trash. rm -rf is the most destructive common command: it recursively and forcefully removes entire trees with no confirmation and no recovery. Always verify your arguments before running it, and use rm -ri when in doubt.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 5 done

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.