本文档风哥主要介绍Linux cp命令的使用方法,包括文件复制、目录复制、覆盖确认、属性保留等内容,参考Red Hat Enterprise Linux 10官方文档,适合运维人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。更多视频教程www.fgedu.net.cn
参考Red Hat Enterprise Linux 10官方文档中的System administration章节 from LinuxDBA视频:www.itpux.com
Part01-基础概念与理论知识
1.1 cp命令基本概念
cp(copy)命令用于复制文件和目录,是Linux系统中最基本的文件管理命令之一。 学习交流加群风哥微信: itpux-com
- 文件复制:复制单个或多个文件
- 目录复制:递归复制整个目录
- 属性保留:保留文件的所有属性
- 备份功能:创建文件的备份副本
1.2 复制模式
1. 文件到文件
cp source_file dest_file
# 将source_file复制为dest_file
2. 文件到目录
cp source_file dest_dir/
# 将source_file复制到dest_dir目录中
3. 多文件到目录
cp file1 file2 file3 dest_dir/
# 将多个文件复制到目标目录
4. 目录到目录
cp -r source_dir dest_dir/
# 递归复制整个目录
5. 复制模式说明
– 目标是文件:创建副本或覆盖
– 目标是目录:复制到目录中
– 目标不存在:创建新文件/目录
– 目标存在:覆盖(需确认或强制)
1.3 cp命令选项
cp命令常用选项:
- -r/-R:递归复制目录
- -p:保留文件属性(权限、时间戳、所有者等)
- -a:归档模式,相当于-dR –preserve=all
- -f:强制复制,不提示确认
- -i:覆盖前提示确认
- -v:显示复制过程
- -u:只复制更新的文件
- -l:创建硬链接而非复制
- -s:创建符号链接而非复制
- -b:覆盖前创建备份
Part02-生产环境规划与建议
2.1 复制策略规划
1. 备份策略
– 重要文件备份前先验证
– 使用时间戳命名备份文件
– 保留多个历史版本
– 定期清理旧备份
2. 迁移策略
– 大文件使用rsync替代cp
– 保留文件属性和权限
– 验证复制完整性
– 记录迁移日志
3. 同步策略
– 使用-u选项只复制更新的文件
– 使用rsync实现增量同步
– 避免重复复制相同内容
4. 安全策略
– 使用-i选项避免误覆盖
– 重要操作前先测试
– 验证目标路径正确性
2.2 最佳实践建议
使用cp命令的最佳实践: 学习交流加群风哥QQ113257174 更多学习教程公众号风哥教程itpux_com
- 保留属性:使用-a或-p选项保留文件属性
- 交互模式:设置alias cp=’cp -i’
- 验证复制:复制后验证文件完整性
- 使用绝对路径:避免路径错误导致的误操作
- 记录日志:重要复制操作记录日志
2.3 性能优化
1. 大文件复制
– 使用rsync替代cp
– 显示进度:rsync -av –progress
– 支持断点续传
2. 大量小文件
– 使用tar打包后复制
– 使用find + cpio
– 使用rsync -a
3. 跨文件系统复制
– 使用rsync -av
– 保留所有属性
– 支持增量复制
4. 性能对比
# 小文件
time cp -r small_files/ /dest/
# 大文件
time rsync -av large_file /dest/
# 大量文件
time tar cf – source/ | (cd /dest && tar xf -)
Part03-生产环境项目实施方案
3.1 cp基础用法
# 1. 复制文件
# cp source.txt dest.txt
# ls -l dest.txt
-rw-r–r–. 1 root root 1234 Apr 2 16:00 dest.txt
# 2. 复制文件到目录
# cp source.txt /tmp/
# ls -l /tmp/source.txt
-rw-r–r–. 1 root root 1234 Apr 2 16:00 /tmp/source.txt
# 3. 复制多个文件到目录
# cp file1.txt file2.txt file3.txt /tmp/
# ls -l /tmp/file*.txt
-rw-r–r–. 1 root root 1234 Apr 2 16:00 /tmp/file1.txt
-rw-r–r–. 1 root root 1234 Apr 2 16:00 /tmp/file2.txt
-rw-r–r–. 1 root root 1234 Apr 2 16:00 /tmp/file3.txt
# 4. 复制目录
# mkdir -p source_dir/sub_dir
# touch source_dir/file1.txt source_dir/sub_dir/file2.txt
# cp -r source_dir dest_dir
# ls -R dest_dir
dest_dir:
file1.txt sub_dir
dest_dir/sub_dir:
file2.txt
# 5. 复制前确认
# cp -i source.txt dest.txt
cp: overwrite ‘dest.txt’? y
# 6. 强制复制
# cp -f source.txt dest.txt
# 7. 显示复制过程
# cp -v source.txt dest.txt
‘source.txt’ -> ‘dest.txt’
# 8. 只复制更新的文件
# cp -u source.txt dest.txt
# 如果source.txt比dest.txt新才复制
# 9. 使用通配符复制
# cp *.txt /tmp/
# cp file[0-9].txt /tmp/
# 10. 复制隐藏文件
# cp -r sourcedir/. destdir/
# 注意:这会复制sourcedir中的所有文件到destdir
3.2 cp高级用法
# 1. 保留文件属性
# cp -p source.txt dest.txt
# ls -l source.txt dest.txt
-rw-r–r–. 1 user group 1234 Apr 2 10:00 source.txt
-rw-r–r–. 1 user group 1234 Apr 2 10:00 dest.txt
# 2. 归档模式复制
# cp -a source_dir dest_dir
# 保留所有属性:权限、时间戳、所有者、符号链接等
# 3. 创建硬链接
# cp -l source.txt hardlink.txt
# ls -li source.txt hardlink.txt
1234567 -rw-r–r–. 2 user group 1234 Apr 2 10:00 hardlink.txt
1234567 -rw-r–r–. 2 user group 1234 Apr 2 10:00 source.txt
# 4. 创建符号链接
# cp -s source.txt symlink.txt
# ls -l symlink.txt
lrwxrwxrwx. 1 root root 10 Apr 2 16:00 symlink.txt -> source.txt
# 5. 覆盖前备份
# cp -b source.txt dest.txt
# ls -l dest.txt*
-rw-r–r–. 1 root root 1234 Apr 2 16:00 dest.txt
-rw-r–r–. 1 root root 1234 Apr 2 10:00 dest.txt~
# 指定备份后缀
# cp -b –suffix=.bak source.txt dest.txt
# 6. 保留指定属性
# cp –preserve=mode,ownership,timestamps source.txt dest.txt
# 7. 复制时显示进度
# rsync -av –progress source.txt /tmp/
sending incremental file list
source.txt
1234 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=0/1)
sent 1,356 bytes received 35 bytes 2,782.00 bytes/sec
total size is 1,234 speedup is 0.89
# 8. 复制并验证
# cp source.txt dest.txt && md5sum source.txt dest.txt
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 source.txt
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 dest.txt
# 9. 复制时修改权限
# cp –no-preserve=mode source.txt dest.txt
# 使用默认权限而非源文件权限
# 10. 复制符号链接指向的文件
# cp -L symlink.txt dest.txt
# 复制符号链接指向的实际文件,而非链接本身
# 11. 复制时保留符号链接
# cp -P symlink.txt dest.txt
# 复制符号链接本身,而非指向的文件
# 12. 复制目录时排除特定文件
# rsync -av –exclude=’*.log’ source_dir/ dest_dir/
3.3 实用案例
# 案例1:配置文件备份脚本
# cat > /usr/local/bin/backup_config.sh << 'EOF'
#!/bin/bash
CONFIG_FILE=$1
if [ -z "$CONFIG_FILE" ]; then
echo "用法: $0 <配置文件>”
exit 1
fi
if [ ! -f “$CONFIG_FILE” ]; then
echo “文件不存在: $CONFIG_FILE”
exit 1
fi
BACKUP_DIR=”/backup/config”
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BASENAME=$(basename “$CONFIG_FILE”)
BACKUP_FILE=”$BACKUP_DIR/${BASENAME}.$TIMESTAMP”
mkdir -p “$BACKUP_DIR”
# 备份文件
cp -pv “$CONFIG_FILE” “$BACKUP_FILE”
# 保留最近10个备份
cd “$BACKUP_DIR”
ls -t ${BASENAME}.* | tail -n +11 | xargs rm -f 2>/dev/null
echo “备份完成: $BACKUP_FILE”
EOF
# chmod +x /usr/local/bin/backup_config.sh
# 案例2:目录迁移脚本
# cat > /usr/local/bin/migrate_dir.sh << 'EOF'
#!/bin/bash
SOURCE_DIR=$1
DEST_DIR=$2
if [ -z "$SOURCE_DIR" ] || [ -z "$DEST_DIR" ]; then
echo "用法: $0 <源目录> <目标目录>”
exit 1
fi
if [ ! -d “$SOURCE_DIR” ]; then
echo “源目录不存在: $SOURCE_DIR”
exit 1
fi
echo “开始迁移: $SOURCE_DIR -> $DEST_DIR”
# 统计文件数量
FILE_COUNT=$(find “$SOURCE_DIR” -type f | wc -l)
echo “文件总数: $FILE_COUNT”
# 复制目录
cp -av “$SOURCE_DIR” “$DEST_DIR”
# 验证复制
DEST_FILE_COUNT=$(find “$DEST_DIR” -type f | wc -l)
if [ “$FILE_COUNT” -eq “$DEST_FILE_COUNT” ]; then
echo “迁移成功!文件数量一致: $DEST_FILE_COUNT”
else
echo “警告: 文件数量不一致!源: $FILE_COUNT, 目标: $DEST_FILE_COUNT”
fi
EOF
# chmod +x /usr/local/bin/migrate_dir.sh
# 案例3:批量复制脚本
# cat > /usr/local/bin/batch_copy.sh << 'EOF'
#!/bin/bash
SOURCE_DIR=$1
DEST_DIR=$2
PATTERN=${3:-"*"}
if [ -z "$SOURCE_DIR" ] || [ -z "$DEST_DIR" ]; then
echo "用法: $0 <源目录> <目标目录> [文件模式]”
exit 1
fi
mkdir -p “$DEST_DIR”
echo “从 $SOURCE_DIR 复制匹配 $PATTERN 的文件到 $DEST_DIR”
# 查找并复制
find “$SOURCE_DIR” -type f -name “$PATTERN” -exec cp -v {} “$DEST_DIR/” \;
echo “复制完成!”
ls -lh “$DEST_DIR”
EOF
# chmod +x /usr/local/bin/batch_copy.sh
Part04-生产案例与实战讲解
4.1 案例1:配置文件备份
# 场景:备份系统重要配置文件
# 1. 创建配置文件备份脚本
# cat > /usr/local/bin/backup_system_config.sh << 'EOF'
#!/bin/bash
BACKUP_ROOT="/backup/system-config"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_ROOT/$TIMESTAMP"
# 创建备份目录
mkdir -p "$BACKUP_DIR"/{etc,sysconfig,nginx,httpd,mysql,ssh}
echo "========================================="
echo "系统配置文件备份"
echo "时间: $(date)"
echo "备份目录: $BACKUP_DIR"
echo "========================================="
# 备份/etc目录下的重要配置
echo "备份/etc配置文件..."
cp -av /etc/passwd "$BACKUP_DIR/etc/"
cp -av /etc/shadow "$BACKUP_DIR/etc/"
cp -av /etc/group "$BACKUP_DIR/etc/"
cp -av /etc/gshadow "$BACKUP_DIR/etc/"
cp -av /etc/fstab "$BACKUP_DIR/etc/"
cp -av /etc/hosts "$BACKUP_DIR/etc/"
cp -av /etc/resolv.conf "$BACKUP_DIR/etc/"
cp -av /etc/sysctl.conf "$BACKUP_DIR/etc/"
cp -av /etc/crontab "$BACKUP_DIR/etc/"
# 备份网络配置
if [ -d /etc/sysconfig/network-scripts ]; then
echo "备份网络配置..."
cp -av /etc/sysconfig/network-scripts/ifcfg-* "$BACKUP_DIR/sysconfig/"
fi
# 备份SSH配置
if [ -d /etc/ssh ]; then
echo "备份SSH配置..."
cp -av /etc/ssh/sshd_config "$BACKUP_DIR/ssh/"
cp -av /etc/ssh/ssh_config "$BACKUP_DIR/ssh/"
fi
# 备份Nginx配置
if [ -d /etc/nginx ]; then
echo "备份Nginx配置..."
cp -av /etc/nginx/nginx.conf "$BACKUP_DIR/nginx/"
cp -av /etc/nginx/conf.d "$BACKUP_DIR/nginx/"
fi
# 备份Apache配置
if [ -d /etc/httpd ]; then
echo "备份Apache配置..."
cp -av /etc/httpd/conf "$BACKUP_DIR/httpd/"
cp -av /etc/httpd/conf.d "$BACKUP_DIR/httpd/"
fi
# 备份MySQL配置
if [ -f /etc/my.cnf ]; then
echo "备份MySQL配置..."
cp -av /etc/my.cnf "$BACKUP_DIR/mysql/"
if [ -d /etc/my.cnf.d ]; then
cp -av /etc/my.cnf.d "$BACKUP_DIR/mysql/"
fi
fi
# 创建备份信息文件
cat > “$BACKUP_DIR/backup_info.txt” << INFO
备份信息
========
备份时间: $(date)
备份主机: $(hostname)
系统版本: $(cat /etc/redhat-release)
内核版本: $(uname -r)
备份内容:
- 系统配置文件
- 网络配置
- SSH配置
- Web服务器配置
- 数据库配置
备份大小: $(du -sh "$BACKUP_DIR" | cut -f1)
INFO
# 打包备份
cd "$BACKUP_ROOT"
tar -czf "$TIMESTAMP.tar.gz" "$TIMESTAMP"
rm -rf "$TIMESTAMP"
echo "========================================="
echo "备份完成!"
echo "备份文件: $BACKUP_ROOT/$TIMESTAMP.tar.gz"
echo "备份大小: $(du -sh "$BACKUP_ROOT/$TIMESTAMP.tar.gz" | cut -f1)"
echo "========================================="
# 清理旧备份(保留最近7个)
cd "$BACKUP_ROOT"
ls -t *.tar.gz | tail -n +8 | xargs rm -f 2>/dev/null
EOF
# chmod +x /usr/local/bin/backup_system_config.sh
# 2. 执行备份
# /usr/local/bin/backup_system_config.sh
=========================================
系统配置文件备份
时间: Fri Apr 2 16:30:00 CST 2026
备份目录: /backup/system-config/20260402_163000
=========================================
备份/etc配置文件…
‘/etc/passwd’ -> ‘/backup/system-config/20260402_163000/etc/passwd’
‘/etc/shadow’ -> ‘/backup/system-config/20260402_163000/etc/shadow’
‘/etc/group’ -> ‘/backup/system-config/20260402_163000/etc/group’
…
‘/etc/nginx/nginx.conf’ -> ‘/backup/system-config/20260402_163000/nginx/nginx.conf’
…
=========================================
备份完成!
备份文件: /backup/system-config/20260402_163000.tar.gz
备份大小: 1.2M
=========================================
4.2 案例2:目录迁移
# 场景:将应用目录迁移到新存储
# 1. 创建迁移脚本
# cat > /usr/local/bin/migrate_application.sh << 'EOF'
#!/bin/bash
SOURCE_DIR=$1
DEST_DIR=$2
if [ -z "$SOURCE_DIR" ] || [ -z "$DEST_DIR" ]; then
echo "用法: $0 <源目录> <目标目录>”
exit 1
fi
if [ ! -d “$SOURCE_DIR” ]; then
echo “源目录不存在: $SOURCE_DIR”
exit 1
fi
LOG_FILE=”/var/log/migration_$(date +%Y%m%d_%H%M%S).log”
log() {
echo “[$(date ‘+%Y-%m-%d %H:%M:%S’)] $1” | tee -a “$LOG_FILE”
}
log “=========================================”
log “目录迁移开始”
log “源目录: $SOURCE_DIR”
log “目标目录: $DEST_DIR”
log “=========================================”
# 统计源目录信息
log “统计源目录信息…”
SOURCE_SIZE=$(du -sh “$SOURCE_DIR” | cut -f1)
SOURCE_FILES=$(find “$SOURCE_DIR” -type f | wc -l)
SOURCE_DIRS=$(find “$SOURCE_DIR” -type d | wc -l)
log “源目录大小: $SOURCE_SIZE”
log “文件数量: $SOURCE_FILES”
log “目录数量: $SOURCE_DIRS”
# 检查目标磁盘空间
DEST_DISK=$(df -h “$(dirname “$DEST_DIR”)” | tail -1 | awk ‘{print $4}’)
log “目标磁盘可用空间: $DEST_DISK”
# 创建目标目录
log “创建目标目录…”
mkdir -p “$DEST_DIR”
# 使用rsync复制(显示进度)
log “开始复制文件…”
rsync -av –progress “$SOURCE_DIR/” “$DEST_DIR/” 2>&1 | tee -a “$LOG_FILE”
# 验证复制
log “验证复制结果…”
DEST_SIZE=$(du -sh “$DEST_DIR” | cut -f1)
DEST_FILES=$(find “$DEST_DIR” -type f | wc -l)
DEST_DIRS=$(find “$DEST_DIR” -type d | wc -l)
log “目标目录大小: $DEST_SIZE”
log “文件数量: $DEST_FILES”
log “目录数量: $DEST_DIRS”
# 比较文件数量
if [ “$SOURCE_FILES” -eq “$DEST_FILES” ]; then
log “[成功] 文件数量一致”
else
log “[警告] 文件数量不一致!源: $SOURCE_FILES, 目标: $DEST_FILES”
fi
# 创建迁移完成标记
touch “$DEST_DIR/.migration_complete_$(date +%Y%m%d_%H%M%S)”
log “=========================================”
log “目录迁移完成”
log “=========================================”
EOF
# chmod +x /usr/local/bin/migrate_application.sh
# 2. 执行迁移
# /usr/local/bin/migrate_application.sh /opt/app /data/app
=========================================
目录迁移开始
源目录: /opt/app
目标目录: /data/app
=========================================
统计源目录信息…
源目录大小: 5.2G
文件数量: 12345
目录数量: 567
目标磁盘可用空间: 100G
创建目标目录…
开始复制文件…
sending incremental file list
…
sent 5.20G bytes received 12,345 bytes 10.40M bytes/sec
total size is 5.20G speedup is 1.00
验证复制结果…
目标目录大小: 5.2G
文件数量: 12345
目录数量: 567
[成功] 文件数量一致
=========================================
目录迁移完成
=========================================
4.3 案例3:批量复制
# 场景:批量复制日志文件到归档目录
# 1. 创建批量复制脚本
# cat > /usr/local/bin/archive_logs.sh << 'EOF'
#!/bin/bash
LOG_DIR=$1
ARCHIVE_DIR=${2:-"/archive/logs"}
DAYS=${3:-7}
if [ -z "$LOG_DIR" ]; then
echo "用法: $0 <日志目录> [归档目录] [天数]”
exit 1
fi
TIMESTAMP=$(date +%Y%m%d)
ARCHIVE_PATH=”$ARCHIVE_DIR/$TIMESTAMP”
echo “=========================================”
echo “日志归档”
echo “源目录: $LOG_DIR”
echo “归档目录: $ARCHIVE_PATH”
echo “归档天数: $DAYS 天前的文件”
echo “=========================================”
# 创建归档目录
mkdir -p “$ARCHIVE_PATH”
# 查找并复制日志文件
echo “查找需要归档的日志文件…”
find “$LOG_DIR” -type f -name “*.log” -mtime +$DAYS -print | while read logfile; do
# 获取相对路径
REL_PATH=${logfile#$LOG_DIR/}
DEST_PATH=”$ARCHIVE_PATH/$REL_PATH”
# 创建目标目录
mkdir -p “$(dirname “$DEST_PATH”)”
# 复制文件
cp -pv “$logfile” “$DEST_PATH”
# 压缩原文件
gzip “$logfile”
done
# 统计归档结果
ARCHIVED_COUNT=$(find “$ARCHIVE_PATH” -type f | wc -l)
ARCHIVED_SIZE=$(du -sh “$ARCHIVE_PATH” | cut -f1)
echo “”
echo “=========================================”
echo “归档完成”
echo “归档文件数: $ARCHIVED_COUNT”
echo “归档大小: $ARCHIVED_SIZE”
echo “归档位置: $ARCHIVE_PATH”
echo “=========================================”
# 打包归档目录
cd “$ARCHIVE_DIR”
tar -czf “$TIMESTAMP.tar.gz” “$TIMESTAMP”
rm -rf “$TIMESTAMP”
echo “压缩包: $ARCHIVE_DIR/$TIMESTAMP.tar.gz”
EOF
# chmod +x /usr/local/bin/archive_logs.sh
# 2. 执行归档
# /usr/local/bin/archive_logs.sh /var/log /archive/logs 7
=========================================
日志归档
源目录: /var/log
归档目录: /archive/logs/20260402
归档天数: 7 天前的文件
=========================================
查找需要归档的日志文件…
‘/var/log/messages-20260326’ -> ‘/archive/logs/20260402/messages-20260326’
‘/var/log/secure-20260326’ -> ‘/archive/logs/20260402/secure-20260326’
‘/var/log/cron-20260326’ -> ‘/archive/logs/20260402/cron-20260326’
…
=========================================
归档完成
归档文件数: 45
归档大小: 125M
归档位置: /archive/logs/20260402
=========================================
压缩包: /archive/logs/20260402.tar.gz
Part05-风哥经验总结与分享
5.1 cp命令总结
- 基础用法:cp source dest
- 递归复制:cp -r source_dir dest_dir
- 保留属性:cp -p 或 cp -a
- 交互模式:cp -i 覆盖前确认
- 更新复制:cp -u 只复制更新的文件
5.2 常见问题解决
# 问题1: 权限不足
# cp source.txt /root/dest.txt
cp: cannot create regular file ‘/root/dest.txt’: Permission denied
# 解决方法:
sudo cp source.txt /root/dest.txt
# 问题2: 目录不存在
# cp source.txt /nonexistent/dest.txt
cp: cannot create regular file ‘/nonexistent/dest.txt’: No such file or directory
# 解决方法:
mkdir -p /nonexistent
cp source.txt /nonexistent/dest.txt
# 问题3: 磁盘空间不足
# cp large_file /dest/
cp: error writing ‘/dest/large_file’: No space left on device
# 解决方法:
df -h /dest/
# 清理空间或更换目标
# 问题4: 覆盖重要文件
# 解决方法:
# 1. 使用-i选项
alias cp=’cp -i’
# 2. 使用-n选项(不覆盖)
cp -n source.txt dest.txt
# 3. 使用备份
cp -b source.txt dest.txt
# 问题5: 符号链接处理
# 复制链接本身
cp -P symlink dest
# 复制链接指向的文件
cp -L symlink dest
# 问题6: 保留SELinux上下文
cp -Z source.txt dest.txt
# 或使用–preserve=context
5.3 实用技巧
# 1. 快速备份文件
backup() {
cp -a “$1” “$1.backup.$(date +%Y%m%d_%H%M%S)”
}
# 2. 复制并重命名
cp source.txt{,.bak}
# 3. 复制到多个目录
echo dir1 dir2 dir3 | xargs -n 1 cp file.txt
# 4. 显示复制进度
# 方法1:使用pv
pv source.txt > dest.txt
# 方法2:使用rsync
rsync -av –progress source.txt dest.txt
# 5. 复制时排除文件
rsync -av –exclude=’*.log’ source/ dest/
# 6. 复制并验证
cp source.txt dest.txt && md5sum source.txt dest.txt
# 7. 复制大量文件
find source -type f | xargs -I {} cp {} dest/
# 8. 复制并修改权限
cp –no-preserve=mode source.txt dest.txt
chmod 644 dest.txt
# 9. 创建文件副本并修改
cp file.txt{,.new}
vim file.txt.new
# 10. 复制目录结构
find source -type d | sed ‘s|^source|dest|’ | xargs mkdir -p
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
