Skip to main content
Blog|
How-to guides

How to copy a file in Linux

|
Mar 30, 2026|7 min read
HOW-TO GUIDESHow to copy a file in LinuxHOSTNEYhostney.comMarch 30, 2026

The cp command copies files and directories. It is one of the most frequently used commands on any Linux server, whether you are making a backup of a configuration file before editing it, duplicating a WordPress installation, or copying assets between directories. The syntax is straightforward but there are flags and behaviors worth understanding, especially around permissions, overwriting, and recursive copying.

This guide covers cp for files and directories, mv for moving and renaming, and the related commands for creating and viewing files that come up in the same workflows.

Copying a single file#

cp source.txt destination.txt

This creates a copy of source.txt named destination.txt in the same directory. If destination.txt already exists, it is overwritten without warning.

Copy to a different directory

cp source.txt /home/user/backups/

Copies source.txt into the /home/user/backups/ directory, keeping the original filename. The trailing slash is not required but makes the intent clearer.

cp source.txt /home/user/backups/source-backup.txt

Copies and renames in one step.

Copy multiple files to a directory

cp file1.txt file2.txt file3.txt /home/user/backups/

All three files are copied into the destination directory. The destination must be a directory when copying multiple files.

Using a wildcard:

cp *.txt /home/user/backups/

Copies all .txt files in the current directory.

Copying directories with -r#

cp does not copy directories by default:

cp mydir /home/user/backups/
cp: -r not specified; omitting directory 'mydir'

You need the -r (recursive) flag:

cp -r mydir /home/user/backups/

This copies mydir and everything inside it, including subdirectories and their contents, into the destination. The result is /home/user/backups/mydir/ with all contents intact.

Copy directory contents without the directory itself

cp -r mydir/* /home/user/backups/

This copies the contents of mydir into backups/ without creating a mydir subdirectory at the destination. Note that * does not match hidden files (dotfiles). To include them:

cp -r mydir/. /home/user/backups/

The /. pattern matches everything including hidden files.

Preserving permissions and timestamps#

By default, cp creates the new file with the current user’s default permissions and the current timestamp. The copy does not inherit the original file’s permissions, ownership, or modification time.

Preserve with -p

cp -p source.txt destination.txt

The -p flag preserves the original file’s mode (permissions), ownership, and timestamps. This matters when copying configuration files, WordPress files, or anything where file permissions need to remain intact.

Preserve everything with -a (archive)

cp -a mydir /home/user/backups/

The -a flag is equivalent to -r -p --preserve=all . It copies recursively, preserves permissions, timestamps, ownership, and symbolic links. This is the flag to use when making a backup copy of a directory where you want the copy to be identical to the original.

For WordPress backups:

cp -a /var/www/html/wp-content /home/user/wp-content-backup

This preserves the ownership (usually www-data ) and permissions (usually 755 for directories, 644 for files) that WordPress requires. Without -a , you would need to manually fix permissions after copying. For large directory trees or remote copies, rsync is more efficient than cp -a because it can resume interrupted transfers and skip unchanged files.

Overwrite protection#

Prompt before overwriting with -i

cp -i source.txt destination.txt

If destination.txt exists, cp asks for confirmation:

cp: overwrite 'destination.txt'? y

This is useful when you are not sure whether the destination already contains important data.

Never overwrite with -n

cp -n source.txt destination.txt

If destination.txt exists, cp silently skips the copy. No prompt, no error, no overwrite. Useful in scripts where you want to copy only if the file does not already exist.

Only overwrite if source is newer with -u

cp -u source.txt destination.txt

The -u flag copies only if the source file is newer than the destination file, or if the destination does not exist. Useful for incremental backups where you only want to update files that have changed.

Verbose output with -v#

cp -rv mydir /home/user/backups/

The -v flag prints each file as it is copied:

'mydir/file1.txt' -> '/home/user/backups/mydir/file1.txt'
'mydir/file2.txt' -> '/home/user/backups/mydir/file2.txt'
'mydir/subdir/file3.txt' -> '/home/user/backups/mydir/subdir/file3.txt'

Useful for verifying that the right files are being copied, especially with wildcard patterns or recursive copies.

Moving and renaming files with mv#

mv moves a file from one location to another. If the source and destination are on the same filesystem, this is nearly instant because mv just updates the directory entry without copying any data. If they are on different filesystems, mv copies the file and then deletes the original.

Move a file

mv source.txt /home/user/documents/

The file is removed from the current directory and placed in the destination.

Rename a file

mv oldname.txt newname.txt

Moving within the same directory is a rename. There is no separate rename command needed for single files.

Move a directory

mv mydir /home/user/backups/

Unlike cp , mv works on directories without a -r flag. The entire directory tree is moved.

mv vs cp

The key difference: mv removes the original, cp does not. Use cp when you want to keep the original. Use mv when you want to relocate or rename.

# Backup before editing (use cp - keep the original)
cp wp-config.php wp-config.php.bak

# Rename a log file for rotation (use mv - replace the original)
mv access.log access.log.old

Creating files#

touch

touch newfile.txt

Creates an empty file if it does not exist. If the file already exists, touch updates its modification timestamp without changing its contents. This is useful for creating placeholder files or updating timestamps that trigger build systems or cron checks.

Create with content using echo

echo "Hello world" > newfile.txt

Creates the file with the specified content. The > operator overwrites the file if it exists. Use >> to append instead of overwrite:

echo "Another line" >> newfile.txt

Create with a heredoc

For multi-line content:

cat > config.txt << 'EOF'
server_name=example.com
port=8080
debug=false
EOF

This creates config.txt with the three lines between << 'EOF' and EOF . The single quotes around EOF prevent variable expansion in the content.

Viewing file contents#

cat

cat filename.txt

Prints the entire file to the terminal. Fine for small files. For large files, the output scrolls past faster than you can read it.

less

less filename.txt

Opens the file in a scrollable viewer. Navigate with arrow keys, search with /pattern , and quit with q . This is the standard way to read log files and configuration files on a server. Unlike cat , less does not load the entire file into memory, so it works fine on gigabyte-sized log files.

head and tail

head -20 filename.txt

Shows the first 20 lines. Useful for checking the top of a log file or configuration file.

tail -20 filename.txt

Shows the last 20 lines. Useful for checking recent log entries.

tail -f /var/log/nginx/access.log

The -f flag follows the file in real time, printing new lines as they are appended. This is how you watch a log file live while testing something. Press Ctrl+C to stop.

Finding files#

If you need to find a file before copying it:

find /var/www -name "wp-config.php"

This searches recursively under /var/www for files named wp-config.php . For a complete guide on finding files by name, size, date, and permissions, see Linux find command: how to find files and processes.

Common WordPress file operations#

Backup wp-config.php before editing

cp -p /var/www/html/wp-config.php /var/www/html/wp-config.php.bak

Always make a backup before editing configuration files. The -p flag preserves permissions so the backup has the same access rights as the original.

Copy a plugin between sites

cp -a /var/www/site1/wp-content/plugins/my-plugin /var/www/site2/wp-content/plugins/

The -a flag preserves the ownership and permissions. After copying, verify the ownership matches what the destination site expects:

ls -la /var/www/site2/wp-content/plugins/my-plugin

Copy uploads to a backup location

cp -a /var/www/html/wp-content/uploads /home/user/uploads-backup-$(date +%Y%m%d)

The $(date +%Y%m%d) appends today’s date to the backup directory name, making it easy to identify when the backup was taken.

For transferring files between servers rather than copying locally, see How to transfer files over SSH using SCP or SFTP commands: a complete reference guide.

Quick reference#

# Copy a file
cp source.txt destination.txt

# Copy to a directory
cp source.txt /path/to/directory/

# Copy a directory recursively
cp -r mydir /path/to/destination/

# Copy preserving permissions and timestamps
cp -p source.txt destination.txt

# Archive copy (recursive + preserve everything)
cp -a mydir /path/to/backup/

# Copy with overwrite prompt
cp -i source.txt destination.txt

# Copy only if source is newer
cp -u source.txt destination.txt

# Move/rename a file
mv oldname.txt newname.txt

# Create an empty file
touch newfile.txt

# View a file
cat file.txt        # print entire file
less file.txt       # scrollable viewer
head -20 file.txt   # first 20 lines
tail -20 file.txt   # last 20 lines
tail -f file.txt    # follow in real time
CommandWhat it does
cp file dest Copy a file
cp -r dir dest Copy a directory recursively
cp -a dir dest Archive copy (preserves everything)
cp -p file dest Preserve permissions and timestamps
cp -i file dest Prompt before overwriting
cp -n file dest Never overwrite existing files
cp -u file dest Copy only if source is newer
mv file dest Move or rename
touch file Create empty file or update timestamp