ZetCode

Linux cp Command

last modified October 23, 2026

The cp (copy) command in Linux copies files and directories. It can copy a single file to a new name, several files into a directory, or whole directory trees, and it offers options to preserve attributes, avoid overwriting, make backups, and handle symbolic links.

The syntax is cp [options] source target or cp [options] source... directory. The examples use GNU cp from coreutils.

Copying a file

The basic form copies a file to a new name.

cp report.txt report-copy.txt

The copy gets the current time as its modification time and is owned by the user who runs cp. If the target exists, it is overwritten without warning.

$ cp report.txt report-copy.txt
$ ls -l report.txt report-copy.txt
-rw-r--r-- 1 jano jano 11 Oct 23 12:52 report-copy.txt
-rw-r--r-- 1 jano jano 11 Jan 15  2026 report.txt

Copying into a directory

When the target is a directory, the files are copied into it under their original names.

cp report.txt backup/
cp a.txt b.txt backup/

With multiple sources, the last argument must be a directory. Wildcards such as cp *.txt backup/ work as well.

$ cp report.txt backup/
$ cp a.txt b.txt backup/
$ ls backup
a.txt
b.txt
report.txt

Copying directories

Directories are copied with the -r (recursive) option.

cp project archive
cp -r project archive
cp -r project archive

Without -r, cp skips the directory. The first recursive copy creates archive as a copy of project. Running the same command again behaves differently: since archive now exists, project is copied inside it. To copy the contents of a directory into an existing one, use cp -r project/. archive/.

$ cp project archive
cp: -r not specified; omitting directory 'project'
$ cp -r project archive
$ tree archive
archive
├── docs
│   └── README.md
└── src
    └── app.py

3 directories, 2 files
$ cp -r project archive
$ tree -d archive
archive
├── docs
├── project
│   ├── docs
│   └── src
└── src

6 directories

Avoiding overwrites

The -i option asks before overwriting, and -n never overwrites existing files.

cp -i draft.txt report.txt
cp -n draft.txt report.txt

We answer n to the prompt, and -n skips the existing file silently, so report.txt keeps its content. Many users define alias cp='cp -i' for interactive shells.

$ echo "draft" > draft.txt
$ cp -i draft.txt report.txt
cp: overwrite 'report.txt'? n
$ cp -n draft.txt report.txt
$ cat report.txt
Q3 results

Verbose output

The -v option prints each copied file.

cp -v a.txt b.txt backup/
cp -rv project/docs docs-copy

Verbose output shows the source and destination of every file, which helps to follow recursive copies.

$ cp -v a.txt b.txt backup/
'a.txt' -> 'backup/a.txt'
'b.txt' -> 'backup/b.txt'
$ cp -rv project/docs docs-copy
'project/docs' -> 'docs-copy'
'project/docs/README.md' -> 'docs-copy/README.md'

Preserving attributes

The -p option preserves the mode, ownership, and timestamps of the files. The -a (archive) option preserves everything and copies directories recursively.

sudo cp key.pem /tmp/plain.pem
sudo cp -p key.pem /tmp/kept.pem
cp -a key.pem latest.txt keep/

The plain copy made by root belongs to root and has a new timestamp, while the -p copy keeps the original owner and date. Preserving ownership requires root. The -a option, equivalent to -dR --preserve=all, also copies symbolic links as links, which makes it the right choice for backups.

$ ls -l key.pem
-rw------- 1 jano jano 7 Jan 15  2026 key.pem
$ sudo cp key.pem /tmp/plain.pem
$ sudo cp -p key.pem /tmp/kept.pem
$ ls -l /tmp/plain.pem /tmp/kept.pem
-rw------- 1 jano jano 7 Jan 15  2026 /tmp/kept.pem
-rw------- 1 root root 7 Oct 23 12:53 /tmp/plain.pem
$ mkdir keep
$ cp -a key.pem latest.txt keep/
$ ls -l keep
total 4
-rw------- 1 jano jano  7 Jan 15  2026 key.pem
lrwxrwxrwx 1 jano jano 10 Oct 23 12:52 latest.txt -> report.txt

Copying only newer files

The -u option copies a file only when the destination is missing or older than the source.

cp -uv a.txt b.txt backup/

We modified a.txt, so it is copied; b.txt is unchanged and skipped. For synchronizing larger trees, rsync is a better tool.

$ echo "new" > a.txt
$ cp -uv a.txt b.txt backup/
'a.txt' -> 'backup/a.txt'

Making backups

The --backup option keeps the existing destination file under a backup name before overwriting it.

cp --backup=numbered b.txt backup/a.txt

Each run renames the previous a.txt to a numbered backup. -b makes simple backups with a tilde suffix.

$ cp --backup=numbered b.txt backup/a.txt
$ cp --backup=numbered b.txt backup/a.txt
$ ls backup
a.txt
a.txt.~1~
a.txt.~2~
b.txt
report.txt

Symbolic links

By default, cp follows a symbolic link given on the command line and copies the file it points to. The -P option copies the link itself.

cp latest.txt copy1.txt
cp -P latest.txt copy2.txt

copy1.txt is a regular file with the content of report.txt, while copy2.txt is another link. In recursive mode with -r, GNU cp copies links as links; -L forces following them.

$ cp latest.txt copy1.txt
$ cp -P latest.txt copy2.txt
$ ls -l copy1.txt copy2.txt
-rw-r--r-- 1 jano jano 11 Oct 23 12:53 copy1.txt
lrwxrwxrwx 1 jano jano 10 Oct 23 12:53 copy2.txt -> report.txt

Creating links instead of copies

The -l and -s options create hard or symbolic links instead of copying data.

cp -l report.txt report-hard.txt
cp -s report.txt report-sym.txt

The hard link shares the inode number with the original, and the link count rose to 2. cp -al creates a tree of hard links, a cheap snapshot technique. See the ln command for more on links.

$ cp -l report.txt report-hard.txt
$ cp -s report.txt report-sym.txt
$ ls -li report.txt report-hard.txt report-sym.txt
2628330 -rw-r--r-- 2 jano jano 11 Jan 15  2026 report-hard.txt
2628430 lrwxrwxrwx 1 jano jano 10 Oct 23 12:53 report-sym.txt -> report.txt
2628330 -rw-r--r-- 2 jano jano 11 Jan 15  2026 report.txt

Keeping the directory structure

The --parents option recreates the source path under the target directory.

cp --parents project/src/app.py project/docs/README.md backup/

Instead of placing both files directly into backup, cp creates the intermediate directories. This is handy for copying selected files while keeping their layout.

$ cp --parents project/src/app.py project/docs/README.md backup/
$ tree backup/project
backup/project
├── docs
│   └── README.md
└── src
    └── app.py

3 directories, 2 files

Common errors

cp reports missing sources, directories without -r, and permission problems.

cp missing.txt backup/
cp project backup/
cp report.txt /etc/

Writing into /etc requires root privileges. Copying requires read permission on the source and write permission on the target directory.

$ cp missing.txt backup/
cp: cannot stat 'missing.txt': No such file or directory
$ cp project backup/
cp: -r not specified; omitting directory 'project'
$ cp report.txt /etc/
cp: cannot create regular file '/etc/report.txt': Permission denied

Best practices for cp

Source

GNU cp manual

In this article, we have used the cp command to copy files and directories, avoid overwrites, preserve attributes, make backups, handle symbolic links, and keep directory structures.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Linux tutorials.