Copying a file in Linux is straightforward once you know what cp treats as a destination: it can be either a new filename or an existing directory. Getting that distinction wrong can put a file somewhere unexpected—or replace a file you meant to keep.
The basic pattern
cp SOURCE DESTINATION
For example, make a backup beside the original:
cp report.txt report-backup.txt
The source stays in place; cp creates another file. If the destination is an existing directory, the copy keeps the source filename:
cp report.txt ~/Documents/
That creates ~/Documents/report.txt. To copy it there under a different name, provide the full destination path:
cp report.txt ~/Documents/report-archive.txt
Relative paths are interpreted from your current working directory. If you are unsure where you are, run pwd; use absolute paths when that makes the source or destination less ambiguous.
Copy several files at once
Put one or more source paths first and an existing destination directory last:
cp index.html styles.css app.js ~/site-backup/
The files are copied into ~/site-backup/ with their original names. The destination directory must already exist. If it does not, create it before copying:
mkdir -p ~/site-backup
cp index.html styles.css app.js ~/site-backup/
A wildcard can stand in for a group of filenames:
cp *.log ~/log-backup/
The shell expands *.log before cp runs. If you are copying important files, check the matches first so you know exactly what will be included:
printf '%s\n' *.log
In Bash, if there are no matches, the unmatched pattern is normally passed to cp literally, and the command reports that it cannot find the file.
Paths with spaces
Quote a path containing spaces so the shell passes it as one argument:
cp "Project Notes.txt" "$HOME/Work Files/Project Notes.txt"
Double quotes still allow variables such as $HOME to expand. Single quotes preserve their contents literally, so they are useful when a path has spaces but no variable needs to expand:
cp 'Project Notes.txt' '/tmp/Work Files/'
You can also escape spaces with backslashes, but quoting is often easier to read when a path has several spaces.
Protect files from accidental replacement
On typical Linux systems, cp replaces an existing destination file without asking. Add -i when you want a confirmation prompt before an overwrite:
cp -i report.txt ~/Documents/report.txt
If the destination exists, answer y to replace it or n to leave it unchanged. If it does not exist, the copy proceeds without a prompt.
An interactive shell may define an alias that changes how cp behaves. Check with:
alias cp
Aliases are not a substitute for explicit options in scripts. Put the behavior you need directly in the command rather than relying on an interactive shell setting.
When cp says “Permission denied”
Copying requires permission to read the source and write to the destination directory. Replacing an existing destination can also require permission to modify that file’s containing directory.
Inspect the paths and their permissions with:
ls -l /path/to/source.txt
ls -ld /path/to/destination
If permissions are the issue, diagnose them before changing anything; this guide to Linux file permissions explains how to inspect and adjust access. Avoid adding sudo automatically. Elevated privileges can write to protected locations, but they do not fix a mistyped path or make an unsafe overwrite a good idea.
If cp says the destination is not a directory, verify that the directory exists and that the path is what you intended. Create a missing directory first rather than assuming cp will create it.
Know when cp is the wrong tool
Plain cp works with paths available on the same machine. It does not transfer a file to another computer over SSH or copy a file into a Docker container. For a transfer to or from a remote host, use a tool such as scp; the SCP file-copy examples cover both directions. Docker has its own docker cp command for transfers between a host and a container.
Directories are another case that needs different options. cp -r or cp -R copies a directory tree recursively, while cp -a is useful when you need archive-mode copying that preserves attributes. Don’t add these flags to a single-file copy unless you have a reason.
A quick decision check
Before running cp, ask:
- Is the source the file I intend to copy?
- Is the destination an existing directory or a new filename?
- Could a file already exist at that destination?
- Do any paths contain spaces that need quoting?
- Am I copying locally, or do I need a remote-transfer tool?
For a simple duplicate, cp source.txt copy.txt is enough. For a safer overwrite, use cp -i; for several files, put the destination directory last. Being precise about the destination is the main habit that makes cp predictable.
I originally published a more detailed version of this guide on the SSHFlow blog.
I'm also building SSHFlow — an SSH client where every server gets its own workspace for terminals, SFTP, code, and databases.
Top comments (0)