假设本地目录结构如下,需要同步到线上服务器 [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 可以概括为:“匹配即跳过”——只要文件或目录的完整路径与给定模式相符,就不会被同步。

  1. 基本用法
rsync -av --exclude='*.tmp' src/ dst/

跳过所有以 .tmp 结尾的文件,无论它们在源目录的哪一层。

  1. 目录 vs 文件
  • --exclude='logs'

    同时跳过名为 logs 的文件和目录。

  • --exclude='logs/'

    末尾加 / 仅跳过名为 logs目录,同名文件不受影响。

  1. 绝对路径排除
rsync -av --exclude='/src/.git' src/ dst/

开头的 / 表示只排除源目录下直接叫 .git 的项目,不会影响子目录里的 .git

  1. 多规则写法
  • 多个 --exclude

    rsync -av --exclude='*.log' --exclude='tmp/' src/ dst/
  • 从文件读取规则:

    rsync -av --exclude-from='exclude.list' src/ dst/

    exclude.list 每行一个模式,例如:

    *.bak
    cache/
    /private
  1. 通配符与示例
模式 匹配对象
*.tmp 所有 .tmp 文件
temp?/ temp1/tempA/ 等单字符目录
report_[0-9].log report_0.logreport_9.log
**/node_modules/ 任意深度的 node_modules 目录
  1. --include 的关系
  • 规则顺序:先 --include,后 --exclude

  • --include 用于“白名单”例外,--exclude 用于“黑名单”过滤。

  • 若想只同步某个目录,可组合:

    rsync -av \
    --include='/data/' \
    --include='/data/**' \
    --exclude='*' \
    src/ dst/
  1. 注意事项
  • 模式区分大小写(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 虽然代码量少,但实际扫描时间会更长。