DEV Community

dpm_bush
dpm_bush

Posted on Originally published at sshflow.com

Copy Files in Linux with cp: Paths, Overwrites, and Common Mistakes

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
Enter fullscreen mode Exit fullscreen mode

For example, make a backup beside the original:

cp report.txt report-backup.txt
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

A wildcard can stand in for a group of filenames:

cp *.log ~/log-backup/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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/'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Is the source the file I intend to copy?
  2. Is the destination an existing directory or a new filename?
  3. Could a file already exist at that destination?
  4. Do any paths contain spaces that need quoting?
  5. 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)