Skip to main content

How to Copy Files in Bash

• 7 min read
bash file operations copy files cp command

Quick Answer: Copy Files in Bash

To copy a file in Bash, use the cp command: cp source.txt destination.txt. For copying directories, use the -r flag: cp -r source/ destination/. Preserve file attributes with the -p flag.

Quick Comparison: File Copying Methods

MethodPurposeCommandBest For
cpCopy filecp source destSimple file copy
cp -rCopy directorycp -r source/ dest/Recursive copy
cp -pPreserve attributescp -p source destBackup/archiving
cp -vVerbosecp -v source destSeeing progress
rsyncAdvanced syncrsync -av source destComplex syncing

Bottom line: Use cp -r for directories, cp -p for preserving attributes.


Method 1: Copy Single File (The Basic Operation)

Copying a single file is straightforward with the cp command. It’s the most common file operation you’ll perform. The basic syntax is simple: source file goes first, destination second.

Basic Single File Copy

Here’s the fundamental pattern:

cp source.txt destination.txt

This copies the file source.txt to a new file named destination.txt. If the destination already exists, it gets overwritten (unless you use -i flag). The original file remains unchanged.

Copy to a Directory

When the destination is a directory (not a new filename), the file keeps its original name:

cp myfile.txt /home/backup/

This copies myfile.txt into /home/backup/ with the same name. This is useful for backing up to a specific folder. Notice the trailing slash isn’t strictly necessary, but it makes your intent clear—you’re copying INTO that directory.

When to Use Single File Copy

Use simple cp when:

  • Copying a single file to a new location
  • Creating a backup with a different name
  • Copying to an existing directory (keeps original name)
  • Speed matters (cp is fast for single files)
  • You want simplicity

Avoid it when:

  • Copying directories (use -r flag instead)
  • You need to preserve all attributes (use -p)
  • The destination might already exist (use -i for safety)

Method 2: Copy Multiple Files

When you need to copy several files to the same destination, list them all before the destination directory.

Copy Multiple Files to Directory

cp file1.txt file2.txt file3.txt /home/backup/

This copies all three files into /home/backup/, keeping their original names. The last argument (the directory) is always the destination.

Copy Using Wildcards

Wildcards make copying easier when files match a pattern:

cp *.txt /home/backup/

This copies all .txt files to the backup directory. Wildcards are expanded by the shell before cp sees them, so cp receives the full list of matching files.

Copy with Verbose Output

See what’s being copied using the -v flag:

cp -v file1.txt file2.txt file3.txt /home/backup/

Output shows each file as it’s copied. Useful when copying many files and you want confirmation of progress.

When to Use Multiple File Copy

Use when:

  • Copying multiple files to one location
  • Using wildcards to match file patterns
  • You want to see progress (-v flag)
  • Destination is always a directory

Method 3: Copy Directories (Recursive Copy)

To copy entire directories with all their contents, use the -r flag for recursive copying. This is essential for backing up folder structures.

Copy Directory and All Contents

cp -r source_dir destination_dir

The -r flag tells cp to copy the directory and everything inside it recursively. If destination_dir doesn’t exist, it gets created. If it does exist, source_dir becomes a subdirectory inside it.

Behavior Note: How Directories Are Copied

# If destination doesn't exist
cp -r source destination
# Result: destination/ contains source's contents

# If destination exists (it's a directory)
cp -r source destination
# Result: destination/source/ contains source's contents

This behavior can be surprising. To ensure you copy the contents, not wrap in an extra folder, add a trailing slash:

cp -r source/ destination/

When to Use Recursive Copy

Use -r when:

  • Copying entire folder structures
  • Backing up project directories
  • You want to preserve the folder layout
  • Moving configurations or data folders

Method 4: Preserve File Attributes

Use the -p flag to preserve permissions, ownership, and timestamps. This is crucial for backups and when attributes matter.

Copy with Attributes Preserved

cp -p original.txt backup.txt

The -p flag preserves:

  • File permissions (mode)
  • Owner and group
  • Timestamps (access and modification times)

Without -p, the copied file gets the default permissions based on umask, and timestamps become the current time.

When Preservation Matters

# Backup scenario: preserve everything
cp -p /etc/config.conf /etc/config.conf.bak

# Script scenario: need exact permissions
cp -p source.sh /usr/local/bin/myscript

Preservation is especially important for:

  • Backing up configuration files
  • Creating clean copies of scripts
  • Maintaining audit trails (timestamps)
  • System administration tasks

When to Use -p Flag

Use -p when:

  • Creating backups (want exact copies)
  • Permissions matter for the copied file
  • Timestamp information is important
  • Copying to locations with strict permission requirements

Skip it when:

  • Destination needs different permissions anyway
  • You’re creating a new version (timestamps should be current)

Method 5: Interactive Copy (Safety First)

Use the -i flag to be prompted before overwriting files. This prevents accidental data loss.

Copy with Confirmation

cp -i source.txt destination.txt

If destination.txt exists, cp asks for confirmation before overwriting. Useful in scripts where accidental overwrites could be bad.

Example Output

cp -i file.txt existing_file.txt
cp: overwrite 'existing_file.txt'?

Respond y to overwrite or n to skip.

When to Use -i Flag

Use -i when:

  • Overwriting important files
  • Running in interactive shells
  • Testing scripts before full deployment
  • You’re unsure if destination exists

Skip it when:

  • You’re certain you want to overwrite
  • In automated scripts (use proper logic instead)

Method 6: Copy Newer Files Only

The -u flag only copies files if the source is newer than the destination. Useful for incremental backups.

Copy Only if Newer

cp -u source.txt dest.txt

If dest.txt exists but is older, it gets overwritten. If dest.txt is newer, it’s skipped. If destination doesn’t exist, the copy happens.

When to Use -u Flag

Use -u for:

  • Incremental backups (don’t re-copy old files)
  • Syncing directories where some files exist
  • Avoiding unnecessary overwrites

Practical Examples

Example 1: Create Timestamped Backup

#!/bin/bash

# Create backup with current timestamp
file="important_file.txt"
backup_dir="/home/backups"

# Create backup dir if needed
mkdir -p "$backup_dir"

# Generate backup with timestamp
timestamp=$(date +%Y%m%d_%H%M%S)
cp -p "$file" "$backup_dir/${file%.*}_$timestamp.${file##*.}"

echo "Backup created: ${file%.*}_$timestamp.${file##*.}"

This preserves the original, adds a timestamp to the backup name, and keeps file attributes intact.

Example 2: Safe Copy Function

#!/bin/bash

safe_copy() {
  local source="$1"
  local destination="$2"

  # Check source exists
  if [ ! -f "$source" ]; then
    echo "ERROR: Source file not found: $source"
    return 1
  fi

  # Ensure destination directory exists
  dest_dir=$(dirname "$destination")
  mkdir -p "$dest_dir" || return 1

  # Copy with preservation
  if cp -p "$source" "$destination"; then
    echo "Successfully copied: $source -> $destination"
    return 0
  else
    echo "ERROR: Copy failed"
    return 1
  fi
}

# Usage
safe_copy "config.txt" "/etc/myapp/config.txt"

This function validates the source, creates destination directories, and reports success or failure.

Example 3: Copy with Verbose Progress

#!/bin/bash

# Copy multiple files with visible progress
echo "Starting backup..."
cp -v file1.txt file2.txt file3.txt /home/backup/ && echo "Backup complete" || echo "Backup failed"

The -v flag shows each file, and the && and || operators chain success/failure handling.

Example 4: Backup Project Directory

#!/bin/bash

# Backup entire project with timestamp
project_dir="/home/user/myproject"
backup_location="/home/backups"

timestamp=$(date +%Y%m%d_%H%M%S)
backup_name="myproject_$timestamp"

# Create backup
cp -r -p "$project_dir" "$backup_location/$backup_name"

# Verify and report
if [ -d "$backup_location/$backup_name" ]; then
  echo "Project backed up to: $backup_location/$backup_name"
  du -sh "$backup_location/$backup_name"
else
  echo "Backup failed"
  exit 1
fi

Combines recursive copy (-r), attribute preservation (-p), timestamped naming, and verification.

Example 5: Conditional Copy (Copy if Newer)

#!/bin/bash

# Copy configuration only if source is newer
config_source="/tmp/new_config.conf"
config_dest="/etc/myapp/config.conf"

if [ -f "$config_source" ] && [ "$config_source" -nt "$config_dest" ]; then
  cp -p "$config_source" "$config_dest"
  echo "Configuration updated"
else
  echo "Configuration is current"
fi

The -nt operator tests if source is newer than destination.

Example 6: Batch Copy with Error Handling

#!/bin/bash

# Copy multiple files, report errors
source_dir="/source"
dest_dir="/destination"
failed=0

for file in "$source_dir"/*.txt; do
  if ! cp -p "$file" "$dest_dir/"; then
    echo "Failed to copy: $(basename $file)"
    ((failed++))
  fi
done

if [ $failed -eq 0 ]; then
  echo "All files copied successfully"
else
  echo "Failed to copy $failed file(s)"
  exit 1
fi

Loops through files, tracks failures, and reports summary.

Method 7: Using rsync for Advanced Copying

For complex scenarios with many files or selective syncing, rsync is more powerful than cp. It’s the professional tool for backups and file synchronization.

Basic rsync Copy

rsync -av /source/ /destination/

The -a flag means “archive” (preserves permissions, timestamps, ownership). The -v flag shows progress.

rsync vs cp Comparison

Featurecprsync
Simple filesâś“ FastSlightly slower
Directoriesâś“ Worksâś“ Better
Large backupsOKâś“ Excellent
Skipping duplicatesNoâś“ Yes
Progress displayNoâś“ Yes
Remote copyingNoâś“ Yes (SSH)
ComplexitySimpleMore options

When to Use rsync

Use rsync when:

  • Syncing between remote systems
  • Large backup operations
  • You want to skip files that already exist
  • Detailed progress reporting helps
  • You need selective copying

Use cp when:

  • Simple one-time file copy
  • Speed for small files matters most
  • You want basic, no-nonsense copying
  • Simplicity is preferred

Quick Reference

# Copy single file
cp source.txt destination.txt

# Copy to directory
cp file.txt /path/to/dir/

# Copy multiple files
cp file1.txt file2.txt file3.txt /destination/

# Copy directory (recursive)
cp -r source_dir destination_dir

# Copy with attributes preserved
cp -p source.txt destination.txt

# Copy with confirmation before overwrite
cp -i source.txt destination.txt

# Copy with progress display
cp -v source.txt destination.txt

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

# Copy everything with all options
cp -rpv source.txt destination.txt

Summary

Start with basic cp for simple file copying. Use -r for directories, -p to preserve attributes, and -i for safety. When you need more sophisticated syncing or large backups, graduate to rsync. Remember to always quote variables ("$var") to handle filenames with spaces properly. Most daily file copying tasks are handled perfectly well by plain cp with appropriate flags for your situation.