在linux系统中,复制文件夹远比复制单个文件复杂,因为目录本身是一个包含多级子节点与元数据的树形结构。若不使用递归参数,cp命令会直接报错并跳过目录。理解文件系统的inode与dentry关系,有助于明白为何必须显式声明递归:shell调用的cp默认只处理普通文件,遇到目录项时需程序主动遍历。

一、使用cp命令复制文件夹
cp是linux自带的基础文件拷贝工具,语法简单但参数含义容易混淆。复制文件夹最核心的参数是-r(递归)与-a(归档)。其中-r仅做递归拷贝,不保证保留链接、权限等属性;-a等同于-dR --preserve=all,会完整保留符号链接、文件权限、拥有者及时间戳,常用于系统备份。
下面演示将/home/user/source目录复制到/tmp/backup下。注意目标路径是否以斜杠结尾,会影响最终生成的目录层级。若目标目录已存在,source会作为其子目录放入;若省略斜杠且目标不存在,则创建新目录并拷贝内容。
# 递归复制,不保留全部属性 cp -r /home/user/source /tmp/backup # 归档模式,保留权限、符号链接等 cp -a /home/user/source /tmp/backup # 查看结果 ls -l /tmp/backup
使用cp -a时,若源目录名后带斜杠(如source/),部分旧版coreutils会把目录内内容直接铺平到目标,而非创建source子目录。这种差异在脚本中可能引发覆盖风险,因此建议在脚本里明确书写不带尾斜杠的源路径,并用mkdir -p预建目标。
cp的不足在于不支持增量传输,每次都是全量读写。当文件夹达数十GB且只需同步少量改动时,效率偏低。此外cp没有内置的进度条,大目录拷贝时用户难以估算剩余时间。
二、使用rsync高效复制文件夹
rsync是一款专注于增量同步的工具,默认只传输源与目标之间的差异块,极大节省带宽与磁盘IO。它既能在本机目录间拷贝,也能通过ssh通道跨主机传输。本地复制时基本语法为rsync 选项 源 目标。
常用参数组合为-avh:a表示归档模式(类似cp -a),v输出变更明细,h以人类可读单位显示大小。若需排除某些缓存目录,可追加--exclude。以下示例将source同步到backup,并忽略其中的node_modules与.git。
# 本地增量复制文件夹 rsync -avh --exclude=node_modules --exclude=.git /home/user/source/ /tmp/backup/ # 通过ssh复制到远程机器 rsync -avh -e ssh /home/user/source/ user@192.168.0.1:/data/backup/
注意上面源路径以斜杠结尾,这代表拷贝source内部内容到目标,而非创建source目录本身。若去掉尾斜杠,rsync会在目标下新建source并放入内容。这个规则与cp略有不同,是初学者最常踩的坑。
rsync还支持--delete参数,使目标目录完全镜像源端,即删除目标中存在但源端已无的文件。该操作危险,建议先使用-n(dry run)模拟。相比cp,rsync在中断后可重跑继续,不必从头开始,非常适合不稳定网络下的文件夹迁移。
三、常见错误与目标路径辨析
许多人在执行cp /a /b后发现/b下没有a的内容,而是报错cp: omitting directory。这是因为遗漏了-r。另一个隐形错误是混用尾斜杠导致目录嵌套错位,例如期望/tmp/backup/source实际却变成/tmp/backup/backup/source。
为避免歧义,可统一采用如下规范:源目录不写尾斜杠,目标目录写尾斜杠且提前mkdir -p。结合rsync时,若想保留源文件夹名称,源不写尾斜杠;若只想倒内容,源写尾斜杠。下表汇总了四种组合的行为差异。
| 命令示例 | 源尾斜杠 | 结果 |
|---|---|---|
| cp -a src dst | 无 | dst/src包含源内容 |
| cp -a src/ dst | 有 | 旧版可能铺平,新版仍建src |
| rsync -a src dst | 无 | dst/src包含源内容 |
| rsync -a src/ dst | 有 | dst直接含源内容 |
掌握上述规则后,linux下复制文件夹不再是易错操作。对于本地一次性备份,cp -a简单可靠;对于频繁同步或跨机拷贝,rsync以增量与容错胜出。实际运维中建议将常用命令写入shell脚本,并配合logger记录每次目录迁移动作,便于审计与回滚。
linuxcp_commandrsync修改时间:2026-08-02 12:09:29