LFCS Phase 1 Part 22: Copying Files with cp Command

Master the Linux cp command for copying files and directories. Learn recursive copying, preserving attributes, interactive mode, and safe file management techniques for LFCS certification.

29 min read

You've just spent hours configuring a critical file, and now you need to make a backup before testing changes. Or perhaps you need to copy an entire project directory to a new location. The cp command is your essential tool for duplicating files and directories in Linux—and mastering it is crucial for both daily administration and the LFCS exam.

The cp (copy) command creates exact duplicates of files and directories, leaving the originals untouched. Unlike cut-and-paste operations, copying is non-destructive and reversible, making it the safest way to create backups, distribute files, and prepare for risky operations.

💡

🎯 What You'll Learn:

  • Basic cp syntax for copying files and directories
  • Understanding source and destination arguments
  • Recursive copying with -r for entire directory trees
  • Interactive mode with -i to prevent accidental overwrites
  • Verbose mode with -v for operation feedback
  • Preserving file attributes with -p (timestamps, permissions, ownership)
  • Archive mode with -a for complete directory backups
  • Copying multiple files to a destination directory
  • The hidden files challenge and solutions
  • Wildcards with cp for bulk operations
  • Real-world backup and migration scenarios

Series: LFCS Certification - Phase 1 (Post 22 of 52)

Previous Post: Part 21: Using Wildcards for Efficient File Management

Next Post: Part 23: Creating and Managing Directories with mkdir


Understanding the cp Command

The cp command copies files and directories from one location to another. It reads the source file(s) and creates new file(s) at the destination with identical content.

Basic Syntax

cp [OPTIONS] SOURCE DESTINATION

Key Components:

  • cp: The copy command
  • OPTIONS: Flags that modify behavior (like -r, -i, -v)
  • SOURCE: The file(s) or directory to copy FROM
  • DESTINATION: Where to copy TO

How cp Works: The Three Scenarios

The cp command behaves differently based on the source and destination:

ScenarioCommandResult
Copy file to new filecp file1 file2Creates file2 with same content as file1
Copy file to existing directorycp file1 /destination/Creates /destination/file1 (keeps original name)
Copy multiple files to directorycp file1 file2 file3 /dest/Copies all files into /dest/

Basic File Copying

Let's start with the most fundamental cp operations.

Example 1: Missing Destination (Error)

cp /etc/passwd

Output:

cp: missing destination file operand after '/etc/passwd'
Try 'cp --help' for more information.

Explanation:

  • cp requires both source AND destination
  • This error tells you: "I know what to copy, but WHERE should I copy it?"

Example 2: Copy to Current Directory

# Copy /etc/passwd to current directory
cp /etc/passwd .

# Verify the copy
ls -l passwd

Output:

-rw-r--r--. 1 centos9 centos9 2184 Oct 31 19:08 passwd

What happened:

  • /etc/passwd is the source (the file to copy)
  • . is the destination (current directory)
  • The file is copied with the same name: passwd
  • The copy is owned by you (centos9), not root
  • Timestamps are updated to the copy time

Understanding the Dot (.)

The . (dot) represents the current directory:

pwd
# Output: /home/centos9

# These are equivalent:
cp /etc/passwd .
cp /etc/passwd /home/centos9/

Both commands copy /etc/passwd to your current directory.


Permission Requirements for Copying

Not all files can be copied. You need read permission on the source file.

Example: Permission Denied

# Try to copy /etc/shadow (root-only file)
cp /etc/shadow .

Output:

cp: cannot open '/etc/shadow' for reading: Permission denied

Explanation:

  • /etc/shadow contains encrypted passwords
  • Only root can read this file
  • Regular users get "Permission denied"
💡

💡 Key Concept: To copy a file, you need:

  1. Read permission on the source file
  2. Write permission in the destination directory
  3. Execute permission on all parent directories in the path

Copying to a New Filename

You can copy a file and give it a different name in one command.

Example: Rename While Copying

# Copy passwd and rename it to passwd_backup
cp passwd passwd_backup

# Verify both files exist
ls -l passwd*

Output:

-rw-r--r--. 1 centos9 centos9 2184 Oct 31 19:08 passwd
-rw-r--r--. 1 centos9 centos9 2184 Oct 31 19:15 passwd_backup

Result:

  • Original file: passwd (unchanged)
  • New copy: passwd_backup (identical content, new timestamp)

Absolute vs Relative Paths

# Absolute path (full path from root)
cp /etc/passwd /home/centos9/my_passwd_copy

# Relative path (from current directory)
cp passwd ../backup/passwd

The Trailing Slash: Directory Confusion

A common beginner mistake is forgetting whether the destination is a file or directory.

Example: Destination is a File, Not Directory

# Copy /etc/passwd to "mydir" (mydir doesn't exist yet)
cp /etc/passwd mydir

# Check what was created
ls -ld mydir

Output:

-rw-r--r--. 1 centos9 centos9 2184 Oct 31 19:09 mydir

What happened:

  • mydir didn't exist
  • cp created a file named mydir
  • The file contains the copy of /etc/passwd

Now try adding a trailing slash:

# Try to copy to mydir/ (with slash)
cp /etc/passwd mydir/

Output:

cp: cannot create regular file 'mydir/': Not a directory

Explanation:

  • The trailing / indicates "this should be a directory"
  • But mydir is a file, not a directory
  • cp refuses with "Not a directory" error

Fix: Create the Directory First

# Remove the file
rm mydir

# Create an actual directory
mkdir mydir

# Now copy works
cp /etc/passwd mydir/

# Verify
ls -l mydir/

Output:

-rw-r--r--. 1 centos9 centos9 2184 Oct 31 19:10 passwd
⚠️

⚠️ Trailing Slash Best Practice:

Always use a trailing slash when copying TO a directory:

  • cp file.txt /backup/ (clear: destination is directory)
  • cp file.txt /backup (ambiguous: is "backup" a file or directory?)

The trailing slash makes your intent clear and prevents errors.


Recursive Copying with -r

The -r flag enables recursive copying of directories and their contents.

Why -r is Required for Directories

# Try to copy a directory without -r
cp mydir backup

Output:

cp: -r not specified; omitting directory 'mydir'

Explanation:

  • Directories can contain files, subdirectories, and nested structures
  • Without -r, cp doesn't know how deep to go
  • -r means "copy this directory AND everything inside it, recursively"

Example: Recursive Directory Copy

# Create a test directory structure
mkdir -p project/src/modules
touch project/README.md
touch project/src/main.py
touch project/src/modules/utils.py

# Copy entire project directory
cp -r project project_backup

# Verify the copy
ls -R project_backup/

Output:

project_backup/:
README.md  src

project_backup/src:
main.py  modules

project_backup/src/modules:
utils.py

What -r does:

  • Copies the directory itself
  • Copies all files inside
  • Copies all subdirectories (and their contents)
  • Maintains the directory structure

Interactive Mode with -i (Safety First!)

The -i flag enables interactive mode, prompting you before overwriting existing files.

Example: Overwriting Without -i (Dangerous!)

# Create two files
echo "original content" > important.txt
echo "new content" > temp.txt

# Copy temp.txt to important.txt (OVERWRITES without warning!)
cp temp.txt important.txt

# Check content
cat important.txt

Output:

new content

What happened:

  • important.txt had "original content"
  • cp silently overwrote it with "new content"
  • The original content is lost forever
  • No warning, no prompt, no undo!

Safe Copying with -i

# Recreate our files
echo "original content" > important.txt
echo "new content" > temp.txt

# Copy with -i (interactive mode)
cp -i temp.txt important.txt

Output:

cp: overwrite 'important.txt'?

Now you can choose:

  • Type y and press Enter: Overwrite the file
  • Type n and press Enter: Cancel, keep original
  • Press Ctrl+C: Cancel immediately

Best Practice: Always use -i when copying files that might already exist at the destination. It's the simplest way to prevent accidental data loss.

Consider creating an alias:

alias cp='cp -i'

Add this to your ~/.bashrc to make it permanent.


Verbose Mode with -v (See What's Happening)

The -v flag enables verbose mode, showing each file being copied.

Example: Verbose Output

# Copy with verbose output
cp -v /etc/passwd backup_passwd

Output:

'/etc/passwd' -> 'backup_passwd'

Explanation:

  • Shows source file: /etc/passwd
  • Shows destination: backup_passwd
  • Confirms the operation completed

Combining -r and -v

# Recursive copy with verbose output
cp -rv project/ project_backup/

Output:

'project/' -> 'project_backup/'
'project/README.md' -> 'project_backup/README.md'
'project/src' -> 'project_backup/src'
'project/src/main.py' -> 'project_backup/src/main.py'
'project/src/modules' -> 'project_backup/src/modules'
'project/src/modules/utils.py' -> 'project_backup/src/modules/utils.py'

When to use -v:

  • Copying many files (verify everything copied)
  • Debugging copy operations
  • Logging backup operations
  • Learning what cp is actually doing

Preserving Attributes with -p

By default, copied files get new timestamps and ownership. The -p flag preserves original attributes.

Example: Default Copy (No Preservation)

# Check original file
ls -l /etc/passwd

Output:

-rw-r--r--. 1 root root 2184 Oct 25 10:00 /etc/passwd
# Copy without -p
cp /etc/passwd my_passwd

# Check the copy
ls -l my_passwd

Output:

-rw-r--r--. 1 centos9 centos9 2184 Oct 31 19:30 my_passwd

Notice:

  • Original owner: root → Copy owner: centos9 (you)
  • Original timestamp: Oct 25 10:00 → Copy timestamp: Oct 31 19:30 (now)
  • Content is identical, but metadata changed

Example: Copy with -p (Preserve Attributes)

# Copy with -p (preserve)
cp -p /etc/passwd my_passwd_preserved

# Check the copy
ls -l my_passwd_preserved

Output:

-rw-r--r--. 1 centos9 centos9 2184 Oct 25 10:00 my_passwd_preserved

What -p preserves:

  • Timestamps: modification time, access time
  • Permissions: file mode (rwxrwxrwx)
  • Ownership: owner and group (if you have permission)
💡

💡 Ownership Note: Regular users can't change file ownership to other users. When you use -p, the copy will have your ownership, even though permissions and timestamps are preserved. Only root can fully preserve ownership.


Archive Mode with -a (Complete Backups)

The -a flag is archive mode: it combines -r (recursive), -p (preserve), and additional options for complete directory backups.

What -a Does

# -a is equivalent to:
cp -dpr
  • -d: Preserve symbolic links as links (don't follow them)
  • -p: Preserve timestamps, permissions, ownership
  • -r: Recursive (copy directories)

Example: Archive Copy

# Copy entire directory structure with all attributes
cp -a ~/project ~/project_backup

# Verify
ls -la ~/project_backup

Use -a when:

  • Creating complete backups
  • Migrating directories between systems
  • Preserving symbolic links
  • Need exact replica of directory tree

Copying Multiple Files

You can copy multiple files to a destination directory in one command.

Syntax for Multiple Files

cp file1 file2 file3 /destination/

Rules:

  • Last argument must be a directory
  • All previous arguments are source files
  • All sources copied into destination directory

Example: Multiple Files

# Create test files
touch doc1.txt doc2.txt doc3.txt

# Create destination
mkdir documents

# Copy all at once
cp doc1.txt doc2.txt doc3.txt documents/

# Verify
ls documents/

Output:

doc1.txt  doc2.txt  doc3.txt

Using Wildcards with cp

# Copy all .txt files
cp *.txt /backup/

# Copy all files starting with "report"
cp report* /archives/

# Copy specific numbered files
cp file[1-5].txt /dest/

Real-world example:

# Back up all configuration files
cp /etc/*.conf /backup/configs/

# Copy all log files from today
cp /var/log/*$(date +%Y-%m-%d)* /backup/logs/

The Hidden Files Challenge

One of the trickiest aspects of cp is copying hidden files (dotfiles).

The Problem: Wildcards Don't Match Dotfiles

# Try to copy all files including hidden
cp -a ./* destination/

# Check what was copied
ls -a destination/

Result:

  • Regular files: ✅ Copied
  • Hidden files (.bashrc, .profile, etc.): ❌ NOT copied

Why?

  • The wildcard * doesn't match files starting with .
  • This is intentional (safety feature)

Solution 1: Explicitly Copy Dotfiles

# Copy regular files
cp -a ./* destination/

# Copy hidden files separately
cp -a ./.[!.]* destination/

Explanation of ./.[!.]*:

  • ./. - Start with dot
  • [!.] - Next character is NOT a dot (excludes . and ..)
  • * - Followed by anything

This pattern matches: .bashrc, .profile, .config But NOT: . (current dir) or .. (parent dir)

Solution 2: Copy Everything with Dot-Asterisk

# Copy both regular and hidden files (careful!)
cp -a ./.* destination/
cp -a ./* destination/

Problems with this approach:

  • ./* copies regular files
  • ./.* copies hidden files BUT also tries to copy . and ..
  • May produce errors about copying directory into itself
# The cleanest solution for copying everything
tar cf - . | (cd destination && tar xf -)

Or with modern tar:

# Create tarball, then extract
tar czf backup.tar.gz .
tar xzf backup.tar.gz -C destination/

Why tar is better:

  • Handles hidden files naturally
  • Preserves all attributes
  • No special wildcard patterns needed
  • Works reliably in scripts
⚠️

⚠️ Hidden Files Best Practice:

For copying entire directories including hidden files:

  1. Best: Use tar for reliable results
  2. Good: Use cp -a source_dir/ dest_dir/ (copies directory itself)
  3. Avoid: Complex wildcard patterns with .* (error-prone)
# Recommended approach
cp -a ~/project/ ~/project_backup/
# This copies the directory AND all contents (including hidden files)

Common cp Options Reference

OptionPurposeExample
-rRecursive: copy directoriescp -r dir1/ dir2/
-iInteractive: prompt before overwritecp -i file1 file2
-vVerbose: show files being copiedcp -v *.txt backup/
-pPreserve: timestamps, permissionscp -p config.txt backup/
-aArchive: -dpr combined (full backup)cp -a ~/data/ /backup/
-uUpdate: copy only newer filescp -u *.txt backup/
-nNo-clobber: never overwritecp -n file.txt backup/
-fForce: overwrite without promptcp -f file.txt dest/
-sSymbolic link: create symlink insteadcp -s file.txt link.txt

Real-World Use Cases

Use Case 1: Configuration Backup Before Editing

# Always backup before editing critical files
sudo cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Edit the file
sudo vim /etc/ssh/sshd_config

# If something breaks, restore:
sudo cp -p /etc/ssh/sshd_config.backup /etc/ssh/sshd_config

Use Case 2: Creating Daily Backups

# Backup entire home directory
cp -a ~ /backup/home_$(date +%Y-%m-%d)/

# Backup specific project
cp -a ~/important_project /backup/project_$(date +%Y-%m-%d_%H%M%S)/

Use Case 3: Distributing Files to Multiple Locations

# Copy configuration to multiple servers (local prep)
mkdir server1 server2 server3
cp config.yaml server1/
cp config.yaml server2/
cp config.yaml server3/

# Or use brace expansion
cp config.yaml server{1,2,3}/

Use Case 4: Migrating Application Data

# Copy entire application directory preserving everything
cp -a /var/www/myapp /var/www/myapp_v2

# Test changes in myapp_v2
# If successful, replace original

Use Case 5: Copying Only Newer Files

# Update backup with only changed files
cp -ruv ~/documents/ /backup/documents/
# -r: recursive
# -u: update (only copy if source is newer)
# -v: verbose (show what's being copied)

🧪 Practice Labs

Time for hands-on practice! These 20 labs will build your cp command mastery.

💡

💡 Lab Setup: Create a practice directory:

mkdir ~/cp-practice
cd ~/cp-practice

Lab 1: Basic File Copying (Beginner)

Task: Copy /etc/hostname to your current directory. Then copy it again with a new name my_hostname.

Show Solution
# Copy to current directory
cp /etc/hostname .

# Verify
ls -l hostname

# Copy to new name
cp hostname my_hostname

# Verify both exist
ls -l hostname my_hostname

Expected result: Two files with identical content but different names.


Lab 2: Understanding Permission Errors (Beginner)

Task: Try to copy /etc/shadow to your current directory. Understand the error.

Show Solution
# Try to copy shadow file
cp /etc/shadow .

# Expected error:
# cp: cannot open '/etc/shadow' for reading: Permission denied

# Explanation:
# - /etc/shadow is readable only by root
# - Regular users cannot read it
# - This is a security feature (contains password hashes)

# Verify permissions
ls -l /etc/shadow
# Output: ----------. 1 root root ... /etc/shadow
# No read permissions for regular users

Key lesson: You need read permission on source files to copy them.


Lab 3: Destination File vs Directory (Beginner)

Task: Create a file called test.txt. Try to copy it to backup (which doesn't exist). Then create backup as a directory and copy again.

Show Solution
# Create test file
echo "test content" > test.txt

# Copy to backup (doesn't exist)
cp test.txt backup

# Check what was created
ls -l backup
# Output: backup is a FILE, not a directory

# Remove the file
rm backup

# Create backup as directory
mkdir backup

# Copy to backup directory
cp test.txt backup/

# Verify
ls -l backup/

Key lesson: If destination doesn't exist, cp creates a FILE (not a directory).


Lab 4: Recursive Directory Copy (Beginner)

Task: Create a directory structure with subdirectories and files. Copy it recursively.

Show Solution
# Create structure
mkdir -p myproject/src/utils
mkdir -p myproject/docs
echo "readme" > myproject/README.md
echo "main code" > myproject/src/main.py
echo "utilities" > myproject/src/utils/helper.py

# Try to copy without -r (will fail)
cp myproject myproject_copy

# Expected error:
# cp: -r not specified; omitting directory 'myproject'

# Copy with -r (recursive)
cp -r myproject myproject_copy

# Verify structure
ls -R myproject_copy/

Key lesson: Must use -r to copy directories.


Lab 5: Interactive Mode Protection (Intermediate)

Task: Create two files. Use -i to safely prevent overwriting.

Show Solution
# Create two files
echo "important data" > important.txt
echo "new data" > temp.txt

# Try to overwrite WITH interactive mode
cp -i temp.txt important.txt

# Prompt appears:
# cp: overwrite 'important.txt'?

# Type 'n' and press Enter (don't overwrite)

# Verify important.txt unchanged
cat important.txt
# Output: important data

Key lesson: Always use -i when copying to files that might already exist.


Lab 6: Verbose Mode (Intermediate)

Task: Copy multiple files with verbose output to see exactly what's happening.

Show Solution
# Create test files
touch file1.txt file2.txt file3.txt

# Create destination
mkdir backup

# Copy with verbose mode
cp -v file1.txt file2.txt file3.txt backup/

Output:

'file1.txt' -> 'backup/file1.txt'
'file2.txt' -> 'backup/file2.txt'
'file3.txt' -> 'backup/file3.txt'

Key lesson: -v shows exactly what files are being copied where.


Lab 7: Preserving Timestamps (Intermediate)

Task: Copy a file with and without -p. Compare timestamps.

Show Solution
# Copy WITHOUT -p
cp /etc/passwd passwd_no_preserve

# Copy WITH -p
cp -p /etc/passwd passwd_preserved

# Compare timestamps
ls -l /etc/passwd
ls -l passwd_no_preserve
ls -l passwd_preserved

Observations:

  • passwd_no_preserve: timestamp is NOW
  • passwd_preserved: timestamp matches original /etc/passwd

Key lesson: Use -p to preserve original timestamps.


Lab 8: Archive Mode (Intermediate)

Task: Use -a to create a complete backup of a directory.

Show Solution
# Create a complex directory
mkdir -p project/{src,docs,config}
echo "code" > project/src/app.py
echo "docs" > project/docs/README.md
echo "cfg" > project/config/settings.ini

# Copy with archive mode
cp -a project project_archive

# Verify
ls -laR project_archive/

What -a preserves:

  • Directory structure
  • All files
  • Timestamps
  • Permissions
  • Symbolic links (if any)

Key lesson: -a is perfect for complete directory backups.


Lab 9: Copying with Wildcards (Intermediate)

Task: Create files with different extensions. Copy only .txt files.

Show Solution
# Create files
touch doc1.txt doc2.txt doc3.txt
touch img1.jpg img2.jpg
touch data.csv

# Create destination
mkdir text_files

# Copy only .txt files
cp *.txt text_files/

# Verify
ls text_files/
# Should show only: doc1.txt doc2.txt doc3.txt

Key lesson: Wildcards work with cp just like with other commands.


Lab 10: Multiple Files to Directory (Intermediate)

Task: Copy several files to a destination directory in one command.

Show Solution
# Create files
echo "file1" > f1.txt
echo "file2" > f2.txt
echo "file3" > f3.txt

# Create destination
mkdir dest

# Copy all in one command
cp f1.txt f2.txt f3.txt dest/

# Verify
ls dest/

Key lesson: Last argument must be a directory when copying multiple files.


Lab 11: Copying Hidden Files (Advanced)

Task: Create hidden files and copy them correctly.

Show Solution
# Create hidden files
touch .config .bashrc .profile regular.txt

# Create destination
mkdir backup

# Try regular wildcard (misses hidden files)
cp * backup/
ls -a backup/
# Only sees regular.txt

# Copy hidden files explicitly
cp .[!.]* backup/

# Verify all files copied
ls -a backup/

Key lesson: Use .[!.]* pattern to match hidden files without matching . and ...


Lab 12: Preventing Overwrites with -n (Advanced)

Task: Use -n (no-clobber) to never overwrite existing files.

Show Solution
# Create files
echo "original" > data.txt
mkdir backup
echo "original" > backup/data.txt

# Try to copy with -n (won't overwrite)
cp -n data.txt backup/

# Check if file was overwritten
cat backup/data.txt
# Still shows: original

# Copy without -n (overwrites silently)
echo "new content" > data.txt
cp data.txt backup/
cat backup/data.txt
# Now shows: new content

Key lesson: -n prevents any overwriting; -i prompts before overwriting.


Lab 13: Update Mode with -u (Advanced)

Task: Copy only files that are newer than the destination.

Show Solution
# Create initial files
echo "version 1" > app.py
mkdir backup
cp app.py backup/

# Wait a moment, then update source
sleep 2
echo "version 2" > app.py

# Copy with -u (only if newer)
cp -u app.py backup/

# Check destination (should be updated)
cat backup/app.py
# Output: version 2

# Try again (source hasn't changed)
cp -uv app.py backup/
# No output - file not copied (destination is up to date)

Key lesson: -u only copies if source is newer than destination.


Lab 14: Combining Multiple Options (Advanced)

Task: Use -riv together for safe, verbose, recursive copy.

Show Solution
# Create structure
mkdir -p source/{dir1,dir2}
echo "file1" > source/file1.txt
echo "file2" > source/dir1/file2.txt

# Copy with combined options
cp -riv source/ dest/

What each option does:

  • -r: Recursive (copy directories)
  • -i: Interactive (prompt before overwrite)
  • -v: Verbose (show each file)

Key lesson: Options can be combined: -riv is same as -r -i -v.


Lab 15: Backup Before Modifying (Advanced)

Task: Create a safe backup workflow before editing a file.

Show Solution
# Create important config file
echo "server=localhost" > config.ini
echo "port=8080" >> config.ini

# STEP 1: Always backup first
cp -p config.ini config.ini.backup

# STEP 2: Edit the file
echo "port=9000" > config.ini

# STEP 3: If changes break, restore
cp -p config.ini.backup config.ini

# Verify restoration
cat config.ini

Workflow:

  1. Backup with -p (preserve timestamps)
  2. Make changes
  3. Test
  4. If broken, restore from backup

Key lesson: Always backup before editing critical files.


Lab 16: Directory Name Preservation (Advanced)

Task: Understand difference between cp -r source dest vs cp -r source/ dest/.

Show Solution
# Create source directory
mkdir source
echo "data" > source/file.txt

# Method 1: cp -r source dest
cp -r source dest1
ls dest1/
# Shows: source/ (directory itself was copied)
ls dest1/source/
# Shows: file.txt

# Method 2: cp -r source/ dest2/
mkdir dest2
cp -r source/* dest2/
ls dest2/
# Shows: file.txt (contents copied, not directory name)

Key lesson: Trailing slash behavior affects whether directory name is preserved.


Lab 17: Copying to Parent Directory (Advanced)

Task: Copy files from subdirectory to parent directory.

Show Solution
# Create structure
mkdir subdir
cd subdir
touch file1.txt file2.txt

# Copy to parent directory
cp file1.txt file2.txt ../

# Or use dot-dot shorthand
cp *.txt ..

# Verify
ls ../

Key lesson: .. represents parent directory.


Lab 18: Bulk Backup Script (Advanced)

Task: Create a script to backup all .conf files from /etc that you can read.

Show Solution
# Create backup directory
mkdir ~/etc_backup

# Copy all readable .conf files (some may fail due to permissions)
cp /etc/*.conf ~/etc_backup/ 2>/dev/null

# Count how many were copied
ls ~/etc_backup/ | wc -l

# List what was backed up
ls -lh ~/etc_backup/

Note: 2>/dev/null suppresses permission denied errors.

Key lesson: Combine cp with wildcards for bulk operations.


Lab 19: Preserving Directory Structure (Advanced)

Task: Copy specific files while maintaining directory structure.

Show Solution
# Create nested structure
mkdir -p project/src/modules
echo "code" > project/src/modules/utils.py

# Can't preserve structure with simple cp
# Use --parents option
cp --parents project/src/modules/utils.py backup/

# Verify structure preserved
ls -R backup/

Key lesson: --parents creates parent directories in destination.


Lab 20: Real-World Daily Backup (Advanced)

Task: Create a complete daily backup solution with timestamp.

Show Solution
# Create backup directory with date
BACKUP_DIR=~/backups/$(date +%Y-%m-%d)
mkdir -p "$BACKUP_DIR"

# Backup important directories
cp -a ~/documents "$BACKUP_DIR/"
cp -a ~/projects "$BACKUP_DIR/"

# Create archive for offsite storage
tar czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"

# Verify
ls -lh ~/backups/
du -sh "$BACKUP_DIR"

Complete backup solution:

  • Timestamped directory
  • Preserves all attributes with -a
  • Compressed archive for storage

Key lesson: Combine cp with timestamps for effective backup workflows.


📚 Best Practices

✅ DO

  • Use -i for safety: cp -i prevents accidental overwrites
  • Backup before editing: cp -p config config.bak
  • Use -a for directories: cp -a dir/ backup/
  • Add trailing slash: cp file /dest/ makes intent clear
  • Use -v for verification: See what's being copied
  • Preserve timestamps: Use -p for backups
  • Test with -n first: Dry run with cp -nv
  • Use wildcards carefully: Test with ls first
  • Check disk space: df -h before large copies
  • Use absolute paths: In scripts for clarity

❌ DON'T

  • Never copy without backup: When overwriting critical files
  • Don't forget -r for directories: Will fail silently
  • Don't assume success: Check exit code or use -v
  • Don't copy to same name: cp file file fails
  • Don't rely on * for hidden files: Use specific patterns
  • Don't copy running databases: Stop service first or use proper backup tools
  • Don't copy device files carelessly: Can cause issues
  • Don't mix up source/destination: Double-check order
  • Don't ignore permission errors: May indicate problems
  • Don't use wildcards blindly: Verify matches first

Backup Workflow Best Practice

# 1. Create timestamped backup directory
BACKUP_DIR=~/backups/$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"

# 2. Copy with all attributes preserved
cp -av ~/important_data "$BACKUP_DIR/"

# 3. Verify the copy
ls -lR "$BACKUP_DIR"

# 4. Create compressed archive
tar czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"

# 5. Test the archive
tar tzf "$BACKUP_DIR.tar.gz" | head

🚨 Common Pitfalls to Avoid

Pitfall 1: Forgetting -r for Directories

# Wrong: Won't copy the directory
cp mydir backup

# Right: Use -r for directories
cp -r mydir backup

Pitfall 2: Silent Overwrites

# Dangerous: Overwrites without warning
cp new.txt important.txt

# Safe: Prompts before overwriting
cp -i new.txt important.txt

Pitfall 3: Copying Over Itself

# This will fail
cp file file
# Error: 'file' and 'file' are the same file

# Also problematic:
cp file ./file  # Same issue

Pitfall 4: Wildcard Surprises

# Creates individual files, not directory copy
cp dir/* newdir/

# Misses hidden files
cp * backup/  # Doesn't copy .bashrc, .config, etc.

Pitfall 5: Lost Timestamps

# Timestamps lost (copy time used)
cp config.ini config.bak

# Timestamps preserved
cp -p config.ini config.bak

Pitfall 6: Running Out of Space

# Check available space first
df -h /destination

# Then copy
cp -a large_directory /destination/
# Copies link target content (not the link itself)
cp symlink dest/

# Preserves symbolic link
cp -d symlink dest/
# Or use -a which includes -d

📝 Command Cheat Sheet

# ===== BASIC COPYING =====
cp source dest                    # Copy file to new name
cp source /path/to/dest/          # Copy file to directory
cp file1 file2 file3 /dest/       # Copy multiple files

# ===== DIRECTORY COPYING =====
cp -r source_dir dest_dir         # Copy directory recursively
cp -a source_dir dest_dir         # Archive copy (preserves everything)

# ===== SAFETY OPTIONS =====
cp -i source dest                 # Interactive (prompt before overwrite)
cp -n source dest                 # Never overwrite
cp -u source dest                 # Update (copy only if newer)

# ===== INFORMATION OPTIONS =====
cp -v source dest                 # Verbose (show files being copied)
cp -p source dest                 # Preserve timestamps and permissions

# ===== COMBINING OPTIONS =====
cp -riv source/ dest/             # Recursive, interactive, verbose
cp -av source/ dest/              # Archive mode with verbose
cp -ruv source/ dest/             # Recursive, update only newer, verbose

# ===== WITH WILDCARDS =====
cp *.txt /backup/                 # Copy all .txt files
cp file[1-5].* /dest/             # Copy file1.*, file2.*, ... file5.*
cp -r dir*/ /backup/              # Copy all directories starting with "dir"

# ===== HIDDEN FILES =====
cp -a source_dir/ dest_dir/       # Copies everything including hidden
cp .[!.]* /dest/                  # Copy hidden files only

# ===== BACKUP PATTERNS =====
cp -p file{,.bak}                 # Creates file.bak from file
cp -p file file.$(date +%Y%m%d)   # Timestamped backup

# ===== REAL-WORLD EXAMPLES =====
# Backup config before editing
sudo cp -p /etc/config /etc/config.backup

# Complete project backup
cp -a ~/project ~/project_backup_$(date +%Y%m%d)

# Copy only changed files
cp -ruv ~/documents/ /backup/documents/

# Safe interactive copy
cp -riv source/ destination/

# Archive with timestamp
BACKUP=~/backup_$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP"
cp -av ~/data "$BACKUP/"

🎯 Key Takeaways

Master These Concepts:

  1. cp syntax: cp [OPTIONS] SOURCE DEST—source first, destination last
  2. Always use -r for directories—cp refuses to copy directories without it
  3. Use -i for safety—prevents accidental overwrites by prompting
  4. Use -a for complete backups—combines -dpr for perfect directory copies
  5. Trailing slash matters/dest/ is clearer than /dest
  6. Wildcards work with cp—but test with ls first
  7. Hidden files need special handling* doesn't match dotfiles
  8. Preserve timestamps with -p—important for backups
  9. Multiple files to directory—last argument must be a directory
  10. Always backup before overwritingcp -p original original.bak

LFCS Exam Tips:

  • Know the difference between -p and -a
  • Understand recursive copying requirements
  • Remember hidden file patterns
  • Practice combining options (-riv, -av)
  • Know how to preserve attributes
  • Understand source/destination order

🚀 What's Next?

You've mastered the cp command for copying files and directories in Linux! You now understand recursive copying, preservation of attributes, interactive safety features, and how to handle the tricky case of hidden files.

In the next post, we'll learn about creating and managing directories with mkdir, including:

  • Basic directory creation
  • Creating parent directories with -p
  • Setting permissions during creation
  • Creating multiple directories at once
  • Understanding directory structure organization
  • Common directory management patterns

The skills you learned with cp will combine perfectly with mkdir as we build out complete file and directory management workflows!


🎉 Congratulations! You've mastered the Linux cp command! You can now safely copy files and directories, create backups, preserve attributes, and handle complex copying scenarios with confidence.

Practice makes perfect: The most common mistake is forgetting -r for directories or losing data with accidental overwrites. Build the habit of using -i and -a for safe, complete copies.

Remember: The best backup is the one you make BEFORE you need it. Use cp liberally to protect your work!

Thank you for reading!

Published on December 13, 2025

Owais

Written by Owais

I'm an AIOps Engineer with a passion for AI, Operating Systems, Cloud, and Security—sharing insights that matter in today's tech world.

I completed the UK's Eduqual Level 6 Diploma in AIOps from Al Nafi International College, a globally recognized program that's changing careers worldwide. This diploma is:

  • ✅ Available online in 17+ languages
  • ✅ Includes free student visa guidance for Master's programs in Computer Science fields across the UK, USA, Canada, and more
  • ✅ Comes with job placement support and a 90-day success plan once you land a role
  • ✅ Offers a 1-year internship experience letter while you study—all with no hidden costs

It's not just a diploma—it's a career accelerator.

👉 Start your journey today with a 7-day free trial

Related Articles

Continue exploring with these handpicked articles that complement what you just read

More Reading

One more article you might find interesting