cp 命令是 Linux/Unix 系统中用于“复制”(copy)文件或目录的基本命令,复制目录与复制文件的关键区别在于,你需要告诉 cp 命令不仅要复制目录本身,还要递归地复制它内部的所有文件和子目录。

核心要点:-r 或 -R 选项
要复制一个目录,你必须使用 -r(或 -R)选项,代表 递归。
语法:
cp -r [源目录] [目标目录]
cp: 命令本身。-r: 递归复制选项,这是复制目录的灵魂。[源目录]: 你想要复制的原始目录的路径。[目标目录]: 你想把目录复制到哪里的路径。
详细用法与示例
示例 1:最基础的目录复制
假设你有一个目录 my_project,你想把它复制到 /tmp 目录下。
# 查看当前目录结构 $ ls my_project other_file.txt # 将 my_project 目录复制到 /tmp 目录下 $ cp -r my_project /tmp # 验证是否复制成功 $ ls /tmp/ my_project # 看,my_project 目录已经成功复制到 /tmp 下了
执行后会发生什么?

- 在
/tmp目录下,会创建一个名为my_project的新目录。 - 这个新目录与原始的
my_project目录拥有完全相同的内容(所有文件和子目录)。
示例 2:复制目录并重命名
你可以在复制的同时,给目录一个新的名字。
# 将 my_project 复制到当前目录,并命名为 my_project_backup $ cp -r my_project my_project_backup # 验证 $ ls my_project my_project_backup other_file.txt
你当前目录下同时存在 my_project 和 my_project_backup 两个内容相同但名字不同的目录。
示例 3:复制目录到另一个目录内部
如果你想将 my_project 复制到 another_folder 目录的内部,而不是旁边。
# 假设 another_folder 已经存在 $ ls another_folder my_project # 将 my_project 复制到 another_folder 内部 $ cp -r my_project another_folder/ # 验证 $ ls another_folder/ my_project # my_project 现在是 another_folder 的子目录了
关键区别:

cp -r my_project another_folder会在another_folder旁边创建一个my_project。cp -r my_project another_folder/会在another_folder内部创建一个my_project,结尾的 是个好习惯,它明确表示目标是一个目录。
重要选项:-a (归档)
在实际使用中,更推荐使用 -a 选项而不是 -r。
语法:
cp -a [源目录] [目标目录]
-a 选项是 dpR 的组合,它做了三件事:
d: 不复制文件本身,而是复制链接(link),这能保持原始文件系统中软链接和硬链接的结构,非常有用。p: 保留文件的属性,包括所有者、权限、时间戳等,这对于备份和系统管理非常重要。R: 递归复制,和-r一样。
-a vs -r 的区别:
| 特性 | cp -r |
cp -a |
推荐场景 |
|---|---|---|---|
| 递归复制 | 是 | 是 | 都可以复制目录 |
| 保留文件属性 | 否 | 是 (权限、所有者、时间戳) | 备份、迁移 |
| 处理链接 | 直接复制链接指向的文件 | 复制链接本身 | 需要保持链接结构的场景 |
| 执行速度 | 通常稍快 | 稍慢,因为需要处理更多元数据 | 速度不是首要考虑因素时 |
示例:
# 使用 -a 进行备份,是最好的实践 $ cp -a my_project /path/to/backup/location/
常见错误与解决方案
错误 1:cp: omitting directory 'my_project'
现象:
当你忘记加 -r 选项时,会看到这个错误。
$ cp my_project /tmp cp: omitting directory 'my_project'
原因:
cp 命令默认只能复制文件,当它遇到一个目录时,为了防止你意外覆盖整个目录,它会拒绝操作并给出警告。
解决方案:
加上 -r 或 -a 选项。
$ cp -r my_project /tmp
错误 2:目标目录已存在,导致覆盖
现象:
如果你尝试将目录 A 复制到已经存在的目录 B 中,A 会成为 B 的子目录,但如果你错误地将 A 复制到 B 的旁边,而 B 内部已经有一个同名文件或目录,可能会导致意外覆盖。
解决方案:
-
使用
-i(交互式) 选项:在覆盖前会提示你确认。$ cp -ri my_project another_folder/
another_folder/my_project已存在,系统会问cp: overwrite 'another_folder/my_project'?,你需要输入y确认。 -
使用
-n(no-clobber) 选项:禁止覆盖已存在的文件。$ cp -rn my_project another_folder/
如果目标已存在,命令会直接跳过,不会执行复制。
| 任务 | 命令 | 说明 |
|---|---|---|
| 简单复制目录 | cp -r 源目录 目标目录 |
最基本的方法,递归复制内容。 |
| 最佳实践 (推荐) | cp -a 源目录 目标目录 |
递归复制,并保留所有属性和链接,最适合备份。 |
| 安全复制 (防覆盖) | cp -ri 源目录 目标目录 |
在覆盖前提示你确认。 |
| 安全复制 (跳过) | cp -rn 源目录 目标目录 |
如果目标已存在,不覆盖,直接跳过。 |
cp -a 是你进行目录复制和备份时的首选,因为它能最大程度地保持原始目录的所有特性。
