PQ
PQ.Hosting

Currency

The cp Command in Linux: Copying Files and Directories with Permissions and Metadata

Author
PQ
March 05, 2026
4 min read
44 views

cp is one of those commands used every day but known at best to a third of its capability. Copying a single file is one line. But copying an entire directory while preserving permissions, timestamps, and symbolic links — skipping files that are already up to date — that is a different story. Here is the full picture.

Basic Usage

Copy a file to another directory:

cp file.txt /path/to/folder/

Copy and rename at the same time:

cp file.txt /path/to/folder/newname.txt

Copy several files to one directory:

cp file1.txt file2.txt file3.txt /path/to/folder/

Copy all files with a specific extension:

cp *.log /var/backup/logs/

Copying Directories: the -r Flag

Without -r, attempting to copy a directory gives the error omitting directory. Recursive copying requires the -r or -R flag:

cp -r /var/www/mysite /var/backup/mysite

One important detail: if the target directory already exists, the source folder is copied inside it. If the target does not exist, it is created with the desired name. This causes confusion on repeated runs.

Preserve Permissions, Owner, and Timestamps: the -p Flag

Plain cp creates a new file with the current date and permissions inherited from umask. For backups this is unacceptable — original metadata must be kept.

The -p flag preserves: permissions, owner, group, timestamps:

cp -p config.conf /backup/config.conf

For directories — combined with -r:

cp -rp /etc/nginx /backup/nginx

Do Not Overwrite Existing Files: Flags -n and -i

Copy only if the file does not exist at the destination:

cp -n source.txt /target/

-n (no-clobber) silently skips a file if it already exists. Essential when filling a directory without risking overwriting current versions.

The -i flag asks for confirmation instead of silently skipping:

cp -i file.txt /target/

Copy Only Newer Files: the -u Flag

-u (update) copies a file only if the source is newer than the existing file at the destination, or if the destination does not have it at all:

cp -u /var/www/html/*.php /backup/html/

This is a rough synchronization equivalent — useful for regular backups of changed files.

See What Is Happening: the -v Flag

By default cp works silently. The -v flag (verbose) prints each copied file:

cp -rv /etc/nginx /backup/nginx

When copying thousands of files this floods the terminal — better to redirect to a log:

cp -rv /var/www/html /backup/html > /tmp/cp_log.txt 2>&1

Force Replace: the -f Flag

If the destination file is write-protected, plain cp stops with an error. The -f flag (force) deletes the existing file first, then copies:

cp -f source.conf /etc/app/config.conf

Use carefully on production servers — -f does not ask for confirmation.

Preserve Symbolic Links: the -d Flag

By default cp -r follows symbolic links and copies the actual content. To copy the link itself:

cp -d symlink /target/

Most often needed when copying /etc/nginx/sites-enabled/ where active configs are symlinks pointing to sites-available.

Flag Combinations for Common Tasks

Backup a directory with all metadata and progress output:

cp -rpv /var/www/mysite /backup/mysite_$(date +%Y%m%d)

Sync a directory, copying only what changed:

cp -ru /var/www/html /backup/html

Quick config backup before editing:

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak

When cp Is Not Enough: rsync

For serious synchronization and backups, cp falls short compared to rsync. rsync can: copy only changed blocks (not whole files), show progress in percentages, work over SSH, and exclude files by pattern.

Basic rsync with preserved permissions and symlinks:

rsync -av /var/www/html/ /backup/html/

The trailing slash after the source matters — without it rsync copies the folder inside the target; with it, only the contents.

Quick Reference

Task Command
Copy a file cp file.txt /target/
Copy and rename cp file.txt /target/newname.txt
Copy a directory cp -r /source/ /target/
Preserve permissions and timestamps cp -p file.txt /target/
Directory with metadata cp -rp /source/ /target/
Do not overwrite cp -n file.txt /target/
Ask before overwriting cp -i file.txt /target/
Only newer files cp -u /source/*.php /target/
With progress output cp -rv /source/ /target/
Force replace cp -f file.txt /target/
Copy symlink itself cp -d symlink /target/
Backup with date stamp cp -rp /source/ /backup/source_$(date +%Y%m%d)

Share this article