cp copies files and directories. The syntax reads left to right — source, then destination — and almost every cp question comes down to what happens when the destination already exists.

The everyday forms #

Copy a file and copy into a directory
$ cp notes.txt notes-backup.txt
$ cp notes.txt ~/Documents/

The first form duplicates the file under a new name. The second copies into an existing directory, keeping the name. Same command, two destinations.

Directories need -r #

cp refuses directories by default — a guard against accidentally copying gigabytes. To copy a whole tree, ask for it:

Copy a directory recursively
$ cp -r project project-snapshot

Copying safely #

FlagBehaviour
-iPrompt before overwriting an existing file
-nNever overwrite; skip silently
-uCopy only when the source is newer or the target is missing
-pPreserve timestamps, owner, and mode
-aArchive mode: recurse and preserve everything, ideal for backups
-vPrint each file as it is copied

-u is the quiet hero for backups: run it repeatedly and only changed files move.

Update a backup, only what changed
$ cp -au src/ backup/src/

Overwriting is silent by default: the second command wins and the first file is gone. In scripts, prefer -n or -i so a mistake is loud instead of quiet.

When a "copy" is really a rename or a relocation, use mv instead — it is instant because it does not duplicate data. And when you want to remove the copies you no longer need, rm is the other half of the story. More in the journal.