你写了一个很棒的程序,想在修改前备份一份 —— 但你输入 cp myapp myapp.bak 后,系统没有任何反馈,你甚至不确定到底成功了没有。
更糟的是,你想复制一个文件夹,输入 cp myfolder myfolder_copy,结果弹出一行错误:cp: omitting directory 'myfolder'。
复制看起来简单,但 cp 命令的细节远比想象中多:目录怎么复制?怎么防止覆盖重要文件?如何保证时间戳不变?
别担心,本文将一次性讲透 cp 命令的所有核心用法,让你在复制文件时不再犹豫。
一、cp 命令的作用与基础语法
cp 是 copy 的缩写,用于复制文件或目录。
cp [选项] 源 目标
💡 默认行为:cp 会静默执行,成功没有提示,失败才会报错。这是 Unix 哲学的典型体现——“没有消息就是好消息”。
二、基础用法:复制文件
1. 复制到新文件(改名)
cp file.txt file_backup.txt
结果:生成一份 file_backup.txt,内容和 file.txt 完全一致。
2. 复制到目标目录(保持原名)
cp file.txt /home/alice/backup/
结果:file.txt 被复制到 /home/alice/backup/file.txt。
3. 同时复制多个文件到目标目录
cp file1.txt file2.txt file3.txt /target_dir/
结果:三个文件全部复制到 /target_dir/ 下。
三、复制目录(-r 或 -R)—— 解决 "omitting directory"
这是新手最容易踩的坑。默认情况下,cp不复制目录,只会报错:
$ cp myfolder/ myfolder_copy/
cp: omitting directory 'myfolder/'
正确用法:添加 -r(递归)
cp -r myfolder/ myfolder_copy/
现在整个目录及其内容都被复制过来了。
⚠️ 注意:-r 和 -R 功能完全相同,任选其一。
复制目录时,斜杠 / 的微妙区别
cp -r myfolder myfolder_copy:复制 myfolder 目录本身,生成 myfolder_copy。cp -r myfolder/ myfolder_copy:如果 myfolder_copy 已存在且是目录,会把 myfolder 的内容复制进去;如果不存在,效果同上。
💡 经验建议:复制目录时,不要加尾部斜杠(myfolder 而不是 myfolder/),行为更可预测。
四、覆盖提示与安全策略(-i、-n、-f)
当你向已存在的目标复制时,cp 会直接覆盖(默认行为)。这可能导致数据丢失。
-i —— 交互确认(推荐新手使用)
cp -i important.txt backup/
cp: overwrite 'backup/important.txt'? y
输入 y 覆盖,n 跳过。
-n —— 不覆盖已存在的文件(保险模式)
cp -n file.txt backup/
如果 backup/file.txt 已存在,则跳过复制。适合批量操作,防止误覆盖。
-f —— 强制覆盖
cp -f file.txt backup/
不询问,直接覆盖。常在脚本中使用。
⚠️ 隐藏大坑:系统可能默认设置了别名
很多 Linux 发行版(如 Ubuntu、CentOS)默认给 cp 设置了别名:
$ alias cp
alias cp='cp -i'
这意味着你输入 cp 实际执行的是 cp -i,每次都会询问是否覆盖。如果你在脚本中期望静默覆盖,可能会卡住。解决方法:
\cp file.txt backup/ # 反斜杠跳过别名
/bin/cp file.txt backup/ # 使用绝对路径
五、保留文件属性(-p、-a)—— 不只是复制内容
默认情况下,cp 复制的新文件会继承当前用户的所有权和当前时间作为修改时间。如果你需要保留原文件的属性(时间戳、所有者、权限等),需要用特殊选项。
-p —— 保留部分属性(preserve)
cp -p file.txt backup/
保留的内容包括:
- 所有者和组(owner/group,需 root 权限才能完全保留)
-a —— 归档模式(archive)⭐ 最推荐
cp -a source_dir/ target_dir/
-a 等同于 -dR --preserve=all,它会:
典型场景:
复制软链接时,-d 的作用
cp -d symlink backup/ # 复制链接本身(而不是指向的文件)
cp symlink backup/ # 默认复制链接指向的实体文件
如果复制软链接时不加 -d 或 -a,系统会复制链接背后的实际文件,可能导致磁盘空间意外膨胀。
六、常用选项总结表
| | | |
|---|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | cp -a project/ project_bak/ |
| | | |
| | | |
| | | |
| | | |
七、实战场景与组合技巧
场景1:备份配置文件,保留时间戳
cp -p /etc/hosts /etc/hosts.$(date +%Y%m%d)
结果:生成 hosts.20250624,保留原始修改时间。
场景2:完整备份整个项目
cp -av /home/alice/project/ /home/alice/project_backup/
-av:归档 + 显示详情,完美保留所有元数据。
场景3:批量复制所有 .conf 文件到备份目录,不覆盖已有文件
cp -n *.conf /backup/configs/
场景4:增量备份(仅当源文件更新时才复制)
cp -uv source_dir/* target_dir/
适合频繁备份少量变更的场景。
八、常见坑与避坑指南
| | |
|---|
| cp myfolder/ backup/ → omitting directory | |
| | |
| ❌ 在cp 前用 sudo 复制普通文件,导致新文件属主变成 root | sudo cp file.txt /backup/ | 除非目标目录需要 root 权限,否则不要用sudo |
| cp file.txt /tmp/backup/ 但 /tmp/backup 不存在,系统会生成一个叫 backup 的文件 | 确保目标目录已存在,或使用mkdir -p 先创建 |
| cp link_to_bigfile backup/ 占用了双倍磁盘空间 | |
| | |
九、cp vs scp vs rsync —— 别搞混
十、总结
cp 是 Linux 中最常用的命令之一,掌握它的核心要点:
- 文件复制
- 目录复制:必须加
-r 或 -a,否则报 omitting directory。 - 覆盖控制:
-i(确认)、-n(不覆盖)、-f(强制),警惕系统别名。 - 保留属性
- 安全第一:重要操作前先用
ls 预览目标目录,或使用 -i 确认。
记住一条黄金法则:不确定目标路径是否正确时,先 ls -ld 目标路径 看一眼。 这能避免你把重要文件复制成别的名字,或覆盖已有内容。
如果你觉得本文对你有帮助,欢迎点赞、推荐、转发,关注我,后续会分享更多Linux入门干货!
文 / 零距技术仓
记录每一次真实的折腾 (#^.^#)
🚀 想看到更多实用折腾技巧?
👉 先关注
💬 评论区说说你的经历或想看的内容
👍 点赞表示支持
🔁 顺手分享给也在折腾的人,让大家都少踩坑 😎