Copying a file sounds boring.
Until you accidentally overwrite the wrong configuration file five minutes before deployment.
On macOS and Linux, the terminal command for copying files is:
cpcp stands for copy, and it is one of those commands that looks almost too simple:
cp SOURCE DESTINATIONBut once you start working with projects, backups, config files, scripts, or servers, you will probably use it constantly.
The important part is not just knowing how to copy something.
It is knowing how to copy it without destroying something else.
Start with the Simplest Copy
Suppose your directory contains:
notes.txtYou want a backup before editing it.
Run:
cp notes.txt notes-backup.txtNow:
lsshows:
notes.txt
notes-backup.txtUnlike mv, which moves or renames the original file, cp leaves the source exactly where it is.
That makes it perfect for quick backups.
Before changing an important configuration file, I often do something like:
cp config.json config.json.backupIt takes two seconds and can save a lot more than two seconds later.
Copy a File into Another Folder
Suppose you have:
report.txtand a directory:
archive/Copy the file into it:
cp report.txt archive/Now you have:
report.txt
archive/report.txtThe original stays where it was.
You can also rename the copied version at the same time:
cp report.txt archive/report-old.txtThat is useful when keeping snapshots of files before making changes.
Copy Multiple Files at Once
You do not need to run cp three times.
If you have:
file-1.txt
file-2.txt
file-3.txtyou can copy all of them into a directory:
cp file-1.txt file-2.txt file-3.txt archive/Here is the rule worth remembering:
When
cpreceives multiple source files, the final argument must be a directory.
So this:
cp file-1.txt file-2.txt backup.txtdoes not mean “combine these two files into backup.txt.”
cp expects backup.txt to be a directory.
Terminal commands are very literal. They do exactly what you ask, not what you were hoping you asked.
Copying Directories: The First Gotcha
Suppose you have a project:
my-app/and try:
cp my-app my-app-backupThat will not work the way a file copy does.
Directories contain other files and possibly other directories, so cp needs to copy them recursively.
Use:
cp -R my-app my-app-backupNow the entire directory structure is copied.
For example:
my-app/
├── index.html
├── style.css
└── images/
└── logo.pngbecomes:
my-app-backup/
├── index.html
├── style.css
└── images/
└── logo.pngYou will also commonly see:
cp -r my-app my-app-backupOn modern macOS and Linux systems, both are commonly used for recursive copies. I generally prefer -R when I want the intent to be obvious.
The Dangerous Part: Existing Files
Here is where cp deserves some respect.
Suppose you have:
old-config.txt
config.txtThen run:
cp old-config.txt config.txtIf config.txt already exists, cp can overwrite it.
No dramatic warning.
No recycle bin.
No “Are you sure?” unless you specifically ask for one.
For safer copying, use:
cp -i old-config.txt config.txtThe -i means interactive.
If the destination exists, cp asks before replacing it.
For important files, I strongly prefer:
cp -i source destinationinstead of blindly trusting my typing.
A Real Developer Use Case
Imagine you are about to edit your shell configuration.
On macOS, that might be:
~/.zshrcBefore touching it:
cp ~/.zshrc ~/.zshrc.backupThen make your changes.
If you completely break your shell setup, restoring it is easy:
cp ~/.zshrc.backup ~/.zshrcThe same idea works for:
.env
nginx.conf
package.json
docker-compose.yml
application.propertiesBefore experimenting:
cp .env .env.backupTiny command. Very cheap insurance.
Preserve File Information
Sometimes you want the copy to keep metadata such as timestamps and permissions where supported.
Use:
cp -p original.txt copy.txtThe -p option means preserve.
This is useful for backups where file metadata matters.
For everyday copying, you may not need it.
For scripts, deployments, or system files, it is worth knowing.
Wildcards Make cp Much Faster
Suppose your directory contains:
report-1.pdf
report-2.pdf
report-final.pdf
notes.txt
photo.jpgYou only want the PDFs.
Instead of typing every filename:
cp *.pdf archive/The shell expands:
*.pdfto every matching PDF file.
The same idea works with:
cp *.txt text-files/or:
cp image*.png images/One warning: before using a wildcard with important files, it is often smart to check what it matches first:
ls *.pdfThen copy:
cp *.pdf archive/That habit prevents surprises.
My Practical cp Workflow
When I am dealing with something important, I usually do this:
pwd
ls -l
cp -i config.json config.json.backup
ls -l config.json*Why?
pwd confirms where I am.
ls confirms the file exists.
cp -i gives me overwrite protection.
The final ls confirms the copy actually happened.
It is slightly slower than smashing commands into the terminal without checking.
It is also considerably faster than recovering the wrong file.
The Commands Worth Remembering
Basic copy:
cp file.txt copy.txtCopy into a directory:
cp file.txt backup/Copy and rename:
cp file.txt backup/file-old.txtCopy multiple files:
cp file1.txt file2.txt backup/Copy a directory:
cp -R project project-backupAsk before overwriting:
cp -i source.txt destination.txtPreserve metadata:
cp -p source.txt destination.txtCopy matching files:
cp *.txt backup/Final Takeaway
The basic cp command is easy:
cp SOURCE DESTINATIONBut the useful part is knowing what happens around it.
Files can be copied directly.
Directories need recursive copying:
cp -RExisting destination files can be overwritten, so when the data matters:
cp -iAnd before experimenting with a configuration file, creating a quick backup with:
cp config config.backupis one of the simplest good habits you can develop.
cp is not a flashy terminal command.
It does not look impressive in a screenshot.
But the day your configuration breaks and this file exists:
config.backupit suddenly becomes one of your favorite commands.