The cp command in Linux is something most people eventually learn after starting with simple right-click and paste file operations. But once you begin working on Linux servers with no GUI, no mouse, and sometimes hundreds of files that must be moved before a deployment, graphical file management is no longer an option. That is where the cp command becomes part of your daily workflow.
If you work with Linux servers, shell scripts, automation tasks, or even just your personal Linux machine, you are going to copy files constantly. This guide is written for anyone who wants to use the cp command correctly, not just mechanically. By the end of this guide, you will understand not only the available cp flags, but also when to use them, why they matter, and what can go wrong when they are used incorrectly.
Note:
If you're just getting started with Linux commands, our Linux commands for beginners guide covers the foundational commands you'll use alongside cp every day.
Examples
What Is the cp Command in Linux?
The cp command in Linux works like a photocopier for your filesystem. You put something in, it produces an exact duplicate somewhere else, and the original stays untouched. That's the whole idea.
More precisely, cp reads the contents of a source file and writes them to a new location. If the destination file doesn't exist yet, it gets created. If it does exist, it gets overwritten silently unless you tell cp otherwise. That silent overwrite is the part people forget, and it causes real data loss when you're moving fast.
cp works on files, groups of files, and entire directory trees. On Ubuntu, Rocky Linux, RHEL, and Debian it behaves the same way since it comes from GNU coreutils, which ships with practically every Linux distro. The flags covered here will work across all of them.
If you're already using commands like ls, mv, or rm in your daily work, cp fits right into the same mental model. You're giving the shell a source and a destination, and it handles the rest.
Syntax and Structure
LinuxTeck.com
cp [OPTIONS] SOURCE DESTINATION
# Multiple: copy several files into one directory
cp [OPTIONS] SOURCE1 SOURCE2 ... DESTINATION_DIR
Breaking this down in plain terms: SOURCE is the file or directory you want to copy. DESTINATION is where the copy should land, which can be a new filename or an existing directory. When you provide multiple sources, the last argument must be a directory. [OPTIONS] are the flags that change how the copy behaves, and they matter a lot depending on what you're doing.
Note:
By default, cp does not copy directories. If you try cp mydir/ /backup/ without any flags, you'll get an error: cp: omitting directory 'mydir/'. You need -r or -R to copy directories recursively.
Common Options and When to Use Them
| Flag | What It Does | When to Use It |
|---|---|---|
| -r / -R | Recursively copy directories and all contents inside | Any time you're copying a folder, not just a file |
| -i | Interactive mode: prompts before overwriting existing files | When destination files might exist and you don't want surprises |
| -f | Force: attempts to open the destination file first; if that fails due to permissions, it unlinks (deletes) the destination and writes a fresh copy — only works if you have write permission on the parent directory | Replacing write-protected files in scripts where you have parent directory write access |
| -p | Preserve: keeps original timestamps, permissions, and ownership | Backups where metadata must match the original |
| -a | Archive: combines -r, -p, and preserves symlinks (equivalent to -dR --preserve=all) | Full directory backups where everything must be identical |
| -u | Update: only copies if source is newer than destination or destination is missing | Syncing directories without overwriting newer files |
| -v | Verbose: prints each file name as it's copied | Debugging scripts or confirming large batch copies |
| -n | No-clobber: never overwrite an existing destination file | Copying new files into a directory without touching existing ones |
| -l | Hard link: creates hard links instead of copying file data | Saving disk space when you need the same file accessible from multiple paths |
| --backup | Automatically creates a backup of any destination file before overwriting | Replacing config files where you want a quick rollback option |
cp Command Examples
I. Copy a Single File to Another Location
This is the most basic use: you have a file and want a copy of it somewhere else. The original stays where it is.
LinuxTeck.com
Tip:
If you leave off the filename in the destination and just provide the directory path, cp keeps the original filename. So cp report.txt /home/user/backup/ produces /home/user/backup/report.txt automatically.
II. Rename a File While Copying
You can copy and rename in a single step. Just give the destination a different filename than the source.
LinuxTeck.com
III. Copy Multiple Files Into a Directory
When you need to move several files to one place, list them all before the destination directory. The destination must already exist as a directory.
LinuxTeck.com
IV. Copy a Directory Recursively
To copy a directory and everything inside it, including subdirectories, you need the -r flag. Without it, cp simply refuses.
LinuxTeck.com
Note:
If /var/www/html_backup already exists, the html directory is placed inside it as a subdirectory — this is how backup scripts accidentally build html/html/html nesting over time. To copy the contents instead of the folder itself, use cp -r /var/www/html/. /var/www/html_backup with a trailing /. on the source.
V. Use Interactive Mode to Avoid Overwriting
When you're not sure if the destination already has a file with the same name, -i prompts you before anything gets overwritten.
LinuxTeck.com
VI. Preserve Permissions and Timestamps
When you copy a file for backup purposes and need the copy to look exactly like the original, including modification time and file permissions, use -p.
LinuxTeck.com
Tip:
Without -p, the copied file gets the current timestamp and the umask-adjusted permissions of the user running the command. That matters a lot if you're backing up config files owned by root with specific permission bits.
VII. Archive Mode for Complete Directory Backup
The -a flag is what most sysadmins reach for when doing a real backup. It preserves everything: permissions, timestamps, ownership, and symlinks. It's equivalent to -dR --preserve=all.
LinuxTeck.com
VIII. Copy Only Newer Files With -u
If you're syncing a working directory to a backup folder and don't want to overwrite files that are already up to date, -u skips any file where the destination is equal or newer.
LinuxTeck.com
IX. Use Wildcards to Copy by File Type
You can pass a glob pattern to cp when you want all files of a certain type from one directory, without listing each one manually. Always make sure the destination directory exists first.
LinuxTeck.com
mkdir -p /backup/logs/
cp /var/log/*.log /backup/logs/
Warning:
If /backup/logs/ does not exist and only one file matches the glob pattern, cp silently creates a plain file named logs instead of a directory. Always run mkdir -p /backup/logs/ before copying with wildcards to guarantee the destination is a directory.
X. Verbose Mode to See What's Being Copied
When copying a large batch of files, -v prints each filename as it gets copied. Useful when you want to confirm a script is working, or when something fails and you want to know which file it stopped on.
LinuxTeck.com
'/etc/nginx/conf.d/default.conf' -> '/backup/nginx_conf/conf.d/default.conf'
'/etc/nginx/sites-available/mysite' -> '/backup/nginx_conf/sites-available/mysite'
XI. Real World: Pre-Deploy Config Backup With Auto Timestamp
Before pushing a deployment on a Rocky Linux or Ubuntu server, a quick habit is to snapshot config files with a timestamp in the name so you always have a rollback point without running a full backup tool.
LinuxTeck.com
Tip:
This pattern works great in shell scripts too. See our guide on automatic Linux backup scripts for how to build this into a scheduled routine.
XII. The Mistake: Overwriting a File You Didn't Mean To
This is the most common cp mistake. You run a copy expecting to create a new file, but the destination already has something with the same name. No warning appears and the existing file is gone.
LinuxTeck.com
cp template.conf /etc/app/config.conf
# CORRECT: prompts before overwriting
cp -i template.conf /etc/app/config.conf
# ALSO CORRECT: use --backup to keep the old version automatically
cp --backup=numbered template.conf /etc/app/config.conf
Warning:
cp has no undo. Once a file is overwritten, the original content is gone unless you had a backup or version control. The --backup=numbered flag creates files like config.conf.~1~ before overwriting, which gives you an instant rollback path with zero extra effort.
Why Getting cp Right Actually Matters
Most people learn cp in five minutes and think that's enough. It's a copy command, how complex can it be? Then they lose a config file on a production server, or they write a backup script that silently clobbers newer files because they forgot -u, or they spend a half hour trying to figure out why their backups have the wrong timestamps and permissions. That's when the flags stop being trivia and start being important.
In enterprise Linux environments, specifically on RHEL, Rocky Linux 8 and 9, and Ubuntu Server, cp shows up constantly in deployment scripts, backup routines, CI/CD pipelines, and configuration management workflows. When it runs correctly with the right flags, it's invisible and reliable. When it runs without proper options in a script that fires at 2am, missing -a on a backup or missing -i on a config replace, it creates real incidents. The GNU coreutils cp man page covers every edge case, and it's worth reading once properly rather than learning the hard way through a broken backup.
There's also the file management angle that's easy to overlook. Commands like cp combine naturally with find for targeted copies based on modification time or file type. That combination unlocks workflows that no GUI file manager can match. Once you're comfortable combining them, you start writing better scripts, handling server tasks faster, and trusting your backup routines more. The cp command in Linux is small, but getting it right is one of those things that separates someone who uses Linux from someone who actually knows it.
Key Takeaways
- Always use
-iwhen copying files manually to destinations that might already have content with the same name. It costs one keypress to confirm and can save hours of recovery work. - Use
-ainstead of just-rwhenever you're doing a real backup. Archive mode preserves permissions, ownership, symlinks, and timestamps together, which plain recursive mode does not. - The
--backup=numberedflag creates a versioned copy of the destination before overwriting it. This is a simple safety net for any script that replaces config files. - When copying directories, the behavior changes based on whether the destination exists. If it doesn't exist,
cp -r src destcreatesdestand puts the contents inside. If it does exist,srcbecomes a subdirectory insidedest. Many people get bitten by this once and then remember it for good. - Use
-ucombined with-rto sync a working directory to a backup without overwriting files that are already current. It's lightweight and fast for daily syncs on the same filesystem. - Combine
cpwith shell date substitution ($(date +%F)) to create timestamped backups in a single command. No extra tools needed. cpis not a sync tool. For cross-server backups or large-scale syncing where you also need deletions mirrored, reach forrsyncinstead.cpexcels at local, targeted copy operations.
FAQ
I ran cp but the file at the destination already had changes I needed. Is there any way to recover?
Unfortunately, plain cp doesn't keep the old version. If you have no snapshot, no --backup flag in use, and no version control, the overwritten content is gone. Going forward, use cp --backup=numbered when replacing files, or at least check with ls -la destination before running the copy. Some distros also let you check filesystem snapshots if LVM or Btrfs is in use.
Why does cp -r put the source folder inside the destination sometimes instead of replacing it?
That's the existing-directory behavior. If the destination path already exists as a directory, cp -r source dest places source inside dest as a subdirectory. If dest doesn't exist yet, cp creates it and puts the contents directly inside. Run it a second time on a system where dest now exists and you'll get a nested copy. Always double-check what exists at the destination first with a quick ls.
Does cp work the same on Ubuntu and Rocky Linux? I use both at work.
Yes, both ship GNU coreutils and the behavior is identical for all the flags covered here. One thing worth knowing: on some systems, cp is aliased to cp -i in a user's shell profile, so interactive prompts appear at the terminal even when you don't type -i. This only affects interactive shells. In a standard shell script (#!/bin/bash), aliases are disabled by default, so your scripts see the real cp behavior regardless. The alias issue only matters when you're typing commands directly at the prompt.
I'm copying a large directory and want to know if it finished correctly. How do I check?
Use -v to watch it in real time, or compare file counts after the copy with find /source | wc -l and find /destination | wc -l. For checksum-level verification, diff -rq source destination will report any differences. If you need progress bars and transfer stats on large operations, rsync -av --progress is worth reaching for instead of bare cp.
My script uses cp to replace a config file, but it fails because the file is read-only. How do I fix that?
The -f flag can help, but not in the way most people expect. It does not grant extra permissions. What it does is suppress the interactive prompt that would normally appear for write-protected files, then attempts to unlink and replace the destination if it cannot be opened for writing. This only succeeds if your script already has write permission on the parent directory. If you are running as a regular user trying to replace a root-owned read-only file, -f will still fail. The real fix in that case is running the script with sudo, which gives you the directory-level access -f needs to actually work.
Can I use cp inside a shell script to back up files automatically on a schedule?
Absolutely, and it's one of the most common uses. Combine cp -a with a dated destination path using $(date +%F) and schedule it with cron. Our automatic Linux backup script guide walks through exactly how to set that up, including log output and error handling. For cross-server or large-volume backups, pair it with rsync for the heavy lifting.
From your first terminal command to advanced sysadmin skills - every guide here is written in plain English with real examples you can run right now.