假设本地目录结构如下,需要同步到线上服务器 [email protected]:/opt/backup/dst/ 目录下
/mnt/d/src/
├── dir_a
│ ├── dir_a1
│ ├── dir_a2
│ │ ├── dir_aa1
│ │ └── file_aa1.txt
│ ├── dir_a3
│ └── file_a1.txt
├── dir_b
├── dir_c
└── file_a.txt
1、--include 参数
--include 选项“白名单”式挑选同步的文件或目录,必须与 --exclude 搭配使用,否则会把所有内容都排除掉。
包含 /dir_a/dir_a2/ 目录,但是排除其同级的其它目录
sshpass -f /mnt/password.txt \
rsync -avz \
-e "ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=60 -p 22" \
--include='dir_a/' \
--include='dir_a/dir_a2/' \
--include='dir_a/dir_a2/**' \
--exclude '*' \
/mnt/d/src/ \
[email protected]:/opt/backup/dst/
💡 注意 --exclude '*'会 排除所有文件和目录(包括中间路径),除非有更早的 –include 显式允许它们通过。
如果仅仅使用
--include 'dir_a/dir_a2/'
--include 'dir_a/dir_a2/**'
虽然指定了目标路径,但 rsync 在到达 dir_a/dir_a2 之前,必须先允许:dir_a/(目录),否则,在扫描到 dir_a 时就被 --exclude '*' 拦截并跳过了,根本不会进入 dir_a/dir_a2。
📌正确做法:显式包含所有父目录,需要 从根开始,逐级允许路径通过
--include 'dir_a/'
--include 'dir_a/dir_a2/'
--include 'dir_a/dir_a2/**'
✅ 最佳实践
如果你只想同步 dir_a/dir_a2,也可以考虑直接指定源路径,避免复杂的 filter:
rsync -avz \
--dry-run \
-e "ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=60 -p 22" \
/mnt/d/src/dir_a/dir_a2/ \
[email protected]:/opt/backup/dst/dir_a/dir_a2/
2、--exclude 参数
--exclude 可以概括为:“匹配即跳过”——只要文件或目录的完整路径与给定模式相符,就不会被同步。
- 基本用法
rsync -av --exclude='*.tmp' src/ dst/
跳过所有以 .tmp 结尾的文件,无论它们在源目录的哪一层。
- 目录 vs 文件
-
--exclude='logs'同时跳过名为
logs的文件和目录。 -
--exclude='logs/'末尾加
/仅跳过名为logs的目录,同名文件不受影响。
- 绝对路径排除
rsync -av --exclude='/src/.git' src/ dst/
开头的 / 表示只排除源目录下直接叫 .git 的项目,不会影响子目录里的 .git。
- 多规则写法
-
多个
--exclude:rsync -av --exclude='*.log' --exclude='tmp/' src/ dst/ -
从文件读取规则:
rsync -av --exclude-from='exclude.list' src/ dst/exclude.list每行一个模式,例如:*.bak cache/ /private
- 通配符与示例
| 模式 | 匹配对象 |
|---|---|
*.tmp |
所有 .tmp 文件 |
temp?/ |
temp1/、tempA/ 等单字符目录 |
report_[0-9].log |
report_0.log … report_9.log |
**/node_modules/ |
任意深度的 node_modules 目录 |
- 与
--include的关系
-
规则顺序:先
--include,后--exclude。 -
--include用于“白名单”例外,--exclude用于“黑名单”过滤。 -
若想只同步某个目录,可组合:
rsync -av \ --include='/data/' \ --include='/data/**' \ --exclude='*' \ src/ dst/
- 注意事项
- 模式区分大小写(Linux 默认)。
- 用
-n或--dry-run先模拟,确认排除效果。 --delete会把目标端多余文件删除,与--exclude配合时务必谨慎。
3、--delete 参数
-delete 参数要放在源目录和目标目录前,并且两个目录结构一定要一致。
4、--dry-run 参数
在实际同步之前,可以使用 --dry-run 选项进行模拟,看看会发生什么变化,而不会真正修改文件。
5、--debug=FILTER 参数
想知道 rsync 为什么忽略文件:一定要用 --debug=FILTER,再配合 --itemize-changes
--debug=FILTER # 输出:哪个文件/目录被忽略,是被 --exclude / --exclude-from / 内置规则忽略的,匹配了哪一条规则
# 示例输出类似:
# [sender] hiding file foo/bar.txt because of pattern *.txt
--itemize-changes # 显示每个文件的处理结果(传输/跳过)
--stats # 最终统计信息
--info=SKIP,DEL # 明确显示跳过和删除的条目
6、-avz 参数
| 参数 | 含义 |
|---|---|
-a |
archive(包含 -rlptgoD 参数) |
-v |
verbose(可被更精细的 info/debug 替代) |
-p |
preserve permissions(-a 已经包含该参数) |
-z |
compress |
7、同文件夹同步其中一部分,include 和 exclude 哪个速度更加快
从执行速度来看,只用 --exclude 通常会更快。
原因
- –exclude 的逻辑是“先列出所有文件,再把要排除的挑出去”。rsync 只需要一次遍历即可决定哪些文件要跳过。
- –include 的逻辑是“先列出所有文件,再把要包含的挑进来”,但 rsync 为了判断哪些路径符合 include 规则,往往需要对每个文件逐条检查 include 模式,规则越多、层级越深,匹配开销就越大。
因此,如果目标只是“去掉少数几个目录或文件”,直接 –exclude 更省时;
如果目标是“只保留少数几个目录”,用 –include 虽然代码量少,但实际扫描时间会更长。