首页
/ rclone sync 命令完全指南:安全同步、删除策略与变更报告

rclone sync 命令完全指南:安全同步、删除策略与变更报告

2026-09-07 16:26:26作者:范靓好Udolf

rclone sync 是 rclone 家族中最常用的命令之一,它的职责是"让源与目标变得完全一致,并且只修改目标端"。本指南围绕官方命令文档 rclone_sync.md 展开,结合 cmd/sync/sync.gofs/sync/sync.go 的源码实现,系统讲解其工作原理、比较规则、删除策略、备份/重命名保护,以及从 v1.65 起引入的变化记录(Logger Flags) 能力。读完本文,你将能安全地使用 rclone sync 完成本地与云端、云端与云端之间的目录级同步,并在数据丢失风险与效率之间做出合理取舍。

核心理念:让两端内容最终一致

rclone sync 会"把源同步到目标,只改变目标"。它不会传输源、目标两端本就一致的文件——判断一致性的依据是文件大小与修改时间(modification time),某些后端上则会退化为使用 MD5 校验和 进行比较(--checksum 可强制以"大小 + 校验和"为准)。

它同 rsync 的经典模型一样,具备"双向清单比对、单向单向写"的特点:

  • 源端多出的文件 → 复制到目标;
  • 两端都有但不同的文件 → 用源覆盖目标;
  • 仅存在于目标端的文件 → 删除(除非是重复对象等特殊情况);
  • 若你不想删除目标端任何文件,请改用 rclone copy 命令。

重要提示:由于 sync 会删除目标端文件从而可能造成数据丢失,官方强烈建议在真正执行前先用 --dry-run 试运行,或用 --interactive/-i 开启交互确认:

rclone sync --interactive SOURCE remote:DESTINATION

在交互模式下,每个删除/覆盖动作都会逐个征询你的意见,是新手最稳妥的起步方式。

同步的是"目录内容",不是目录本身

rclone sync 始终同步目录的内容,而非目录本身。当 source:path 指向一个目录时,被复制的是 source:path 里面的内容,而不是"目录名 + 内容"。例如:

rclone sync /home/user/pics remote:backup

得到的是 remote:backup 中直接出现 /home/user/pics 下的文件,而不会出现 remote:backup/pics/... 这一层。

  • 如果 dest:path 不存在,rclone 会先创建它,再把源内容放进去;
  • 若对"目录 vs 内容"仍有疑惑,可进一步阅读 rclone copy 命令文档 中的扩展说明。

覆盖写入与进度展示

  • 使用 -P / --progress 可以实时查看传输统计;
  • 使用 -v / --verbose 可以输出更多调试信息(可重复 -vv 叠加);
  • 目标端根目录的修改时间与元数据默认不会被同步(这是社区已知行为,对应仓库 issue #7652 有详细讨论)。

数据安全机制:什么情况下目标文件不会被删除

目标端文件的删除并非无条件的,以下几种场景 rclone 会刻意"手下留情",这一点与 fs/sync/sync.go 的运行逻辑严格对应:

场景 行为
过程中任何环节出现错误 目标端文件不会删除。源码中在 deleteMode == DeleteModeAfter 阶段会检查 currentError(),一旦有错且未指定 --ignore-errors,将直接打印 fs.ErrorNotDeleting 并跳过删除阶段(见 sync.go
重复对象(duplicate objects) 同一名字在支持该特性的后端上存在多个对象时,暂不处理,不会当作正常删除;若收到 "Duplicate object/directory found in source/destination - ignoring" 报错,需要用 rclone dedupe 命令去重
被过滤规则排除的文件 不会被删除,除非显式指定 --delete-excluded
符号链接 本地文件系统上的 symlink 默认既不会传输也不会删除,除非使用 --links 标志

也就是说,"删除"始终发生在同步成功的前提下。想强制打破"出错即停删"的保险,可显式传入 --ignore-errors(详见后文 Sync Options 表)。

关于"同步重叠加载(overlapping remotes)"的限制

rclone 无法同步互相重叠的源与目标。从源码看,newSyncCopyMove 在删除模式非关闭或执行 move 时,会调用 operations.OverlappingFilterCheck 做重叠检测,一旦发现重叠加载(如把 remote:dir 同步到 remote:dir/subdir),直接抛出 fs.ErrorOverlapping 致命错误(见 sync.go)。

不过官方提供两条变通路径:

  1. filter 规则在同步中排除掉目标所在位置;
  2. 在目标目录内放置一个 exclude-if-present 标记文件(如 .rclone-exclude),再同步到"位于源目录内部的目标目录"。该场景下结合 --exclude-if-present 即可实现自包含的增量更新。

修改时间与元数据同步

  • 只要后端支持,rclone 会尽力同步文件和目录的修改时间;
  • 目录修改时间的同步条件相当苛刻(后端需支持空目录/目录 modtime 写入),源码中由 setDirModTimesetDirModTimeAfter 等状态位控制,见 sync.go
  • 若需要同步文件的自定义元数据(Metadata),必须显式加 --metadata / -M,并保证两端后端都具备读写元数据能力;
  • 若同时希望空目录也被搬运到目标端,需要加 --create-empty-src-dirsrclone sync 独有,定义于 cmd/sync/sync.go)。

命令语法与 Sync 专属选项

rclone sync source:path dest:path [flags]

rclone sync 要求恰好两个位置参数(源码中通过 cmd.CheckArgs(2, 2, ...) 校验)。当第一个参数解析出的是具体文件而非目录时,命令会退化为单文件复制(内部走 operations.CopyFile,见 cmd/sync/sync.go)。

除 sync 命令自己的标志外,它还注册并复用了 Copy Options、Filter Options、Listing Options 以及全局的 Important Options。下表为 sync 专属选项:

选项 说明
--absolute 在输出路径前加前导 /
--combined string 把所有变更汇总写到一个文件(变化报告,详见 Logger Flags 一节)
--create-empty-src-dirs 同步后在目标端创建空的源目录
--csv 以 CSV 格式输出
--dest-after string 报告同步结束后目标端将存在的所有文件
--differ string 把两端都有的"不匹配文件"名单写到该文件
-d, --dir-slash 目录名后追加 /(默认 true)
--dirs-only 只列出目录
--error string 把(哈希或读取)出错的文件写到该文件
--files-only 只列出文件(默认 true)
-F, --format string 输出格式,参见 lsf 帮助(默认 "p"
--hash 在格式中使用 h 时选用的哈希:MD5|SHA-1|DropboxHash(默认 md5
-h, --help 查看 sync 命令帮助
--match string 把匹配(相同)文件写到该文件
--missing-on-dst string 把"目标端缺失(仅源端有)"的文件写到该文件
--missing-on-src string 把"源端缺失(仅目标端有)"的文件写到该文件
-s, --separator string 格式化输出项之间的分隔符(默认 ;
-t, --timeformat string 自定义时间格式,见 lsf 文档(默认:2006-01-02 15:04:05

其中 --differ--missing-on-src--missing-on-dst--match--error--combined--dest-after 均属于变化记录(Logger Flags) 体系,由 fs/operations/operationsflags/operationsflags.go 统一注册,并把 -F/-t/-s/-d/--hash/--files-only/--dirs-only/--csv/--absolute 一并纳入 sync 命令帮助。

变化记录(Logger Flags):像 rsync 的 itemize 一样"预告"每个文件

从某版本起,rclone sync 支持把"每个文件将被如何处理"写入报告,概念上类似 rsync 的 --itemize-changes,但它是边执行边逐文件记录,更像是对"应该发生什么"的预测(实际结果可能因中途错误而不同)。

分组报告标志

--differ--missing-on-dst--missing-on-src--match--error 这五个标志会把对应路径每行一个写入指定的文件名;文件名传 - 则写到标准输出(stdout)。它们各自只输出一类路径,例如 --differ 只输出"源和目标都存在但内容不同"的文件。

--combined 汇总报告

--combined string 生成一个包含全部文件路径的报告,每条记录形如"一个符号 + 空格 + 路径",符号语义如下(与 diff 文件的记号类似):

符号 含义
= path 源和目标中均存在,且完全相同
- path 源端缺失,因此只存在于目标端(意味着将要被删除)
+ path 目标端缺失,只存在于源端(意味着将要被复制)
* path 源和目标都有,但内容不同(意味着将被覆盖)
! path 读取或哈希源/目标时出错

--dest-after:目标端最终清单

--dest-after string 会生成一份"同步完成之后目标端应有的文件清单",格式标志与 rclone lsf 一致,可用 -F 自定义输出字段(支持哈希、modtime 等可选列),通过 --timeformat--separator--csv--absolute 等微调格式。

使用示例

# 把差异(两端都有但不一致的文件)写到 differ.txt
rclone sync --differ differ.txt /home/user/pics remote:backup

# 把全部变更汇总打印到屏幕
rclone sync --combined - -i /home/user/pics remote:backup

# 同步完成后,目标端将有哪些文件(CSV 格式)
rclone sync --dest-after after.csv --csv --dry-run /home/user/pics remote:backup

# 找出"目标独有、疑似可清理"的文件(即 sync 将删除的对象)
rclone sync --missing-on-src orphans.txt --dry-run /home/user/pics remote:backup

Logger Flags 的已知限制

这些记录标志目前不支持或未完全支持以下场景,使用时需注意:

  • --max-duration / CutoffModeHard(硬性时间/流量截断);
  • --compare-dest / --copy-dest
  • 整个目录被一次性服务端 move 的情况;
  • 高层级(high-level)重试会产生重复记录,建议搭配 --retries 1 关闭重试;
  • 部分不常见的错误场景。

此外,当开启 --no-traverse 时,所有涉及"只存在于目标端"的日志要么不完整、要么完全缺失——因为 rclone 根本不会遍历目标端目录树。相关警告也在 operationsflags.goConfigureLoggers 中做了显式提示。每个文件都是在执行过程中被记录的(而非结束后统一统计),所以报告更适合用来预测与审计,而不是作为最终交割凭据。

Copy Options:比较与跳过程序的控制

sync 复用了所有复制类命令共用的标志,用于控制"什么算相同、什么需要重传":

选项 说明
--check-first 在启动传输之前先完成全部比对(checks),再统一开始传输
-c, --checksum 依据"大小 + 校验和"判断变化(校验和不可用时退回只看大小)
--compare-dest stringArray 比较时额外纳入这些服务端路径(增量式同步,不复制)
--copy-dest stringArray 隐含 --compare-dest,并会从这些路径把文件服务端复制进目标端
--cutoff-mode HARD|SOFT|CAUTIOUS 到达 --max-transfer 上限后的停止策略(默认 HARD
--ignore-case-sync 同步时忽略文件名大小写差异
--ignore-checksum 跳过拷贝后的校验和复核
--ignore-existing 跳过目标端已存在的所有文件
--ignore-size 忽略大小比较,改用 modtime 或校验和
-I, --ignore-times 不因"大小 + 时间相同"而跳过——无条件全部传输
--immutable 不修改文件;若目标已有文件被改动则直接报错失败
--inplace 直接写入目标文件,而不是先下载到临时文件再原子改名
-l, --links 将符号链接转换为带 .rclonelink 后缀的普通文件(反之亦然)
--max-backlog int 同步/检查队列中允许的最大积压对象数(默认 10000)
--max-duration Duration 数据传输的最大时长上限(默认 0s 即不限)
--max-transfer SizeSuffix 传输的数据量上限(默认 off)
-M, --metadata 复制对象时保留元数据
--modify-window Duration 视为"相同"的最大时间差(默认 1ns,跨 FS 时按精度自动放宽)
--multi-thread-chunk-size SizeSuffix 多线程下载/上传的分块大小(默认 64Mi
--multi-thread-cutoff SizeSuffix 超过此大小的文件启用多线程下载(默认 256Mi
--multi-thread-streams int 多线程下载使用的流数(默认 4)
--multi-thread-write-buffer-size SizeSuffix 多线程模式下的内存写缓冲(默认 128Ki
--name-transform stringArray 在复制过程中变换路径名
--no-check-dest 不检查目标端,无条件复制
--no-traverse 不遍历目标文件系统(牺牲删除准确性换取速度)
--no-update-dir-modtime 不更新目录修改时间
--no-update-modtime 文件一致时不更新目标端 modtime
--order-by string 传输排序规则,如 'size,descending'
--partial-suffix string 不使用 --inplace 时,临时文件的后缀(默认 .partial
--refresh-times 刷新远端文件 modtime
--server-side-across-configs 允许服务端操作跨越不同 remote 配置
--size-only 只按大小判断,忽略 modtime 与校验和
--streaming-upload-cutoff SizeSuffix 未知大小文件切换为分块上传的阈值(默认 100Ki
-u, --update 跳过"目标端比源端更新"的文件

控制"跳过"的核心变量

默认判断"文件是否一致"时,rclone 依次参考大小与 modtime(部分后端用哈希)。你可以用下面几种方式调整,它们直接映射为源码中 marching/checker 阶段的比较逻辑:

  • -c/--checksum--size-only--modify-window--ignore-times 决定"比较口径";
  • -u/--update 是单向增量语义(不覆盖较新的目标),适合"只回填、不倒退";
  • --no-check-dest / --no-traverse 用于追求吞吐、容忍目标端不完全清理的场景;
  • --max-transfer + --cutoff-mode 控制带宽配额。

Sync Options:删除、备份与重命名策略

这些标志仅用于 sync 类命令(sync、bisync 等),是 sync 区别于 copy 的关键:

选项 说明
--backup-dir string 被覆盖/删除的文件先移到以 DIR 为基础的层级中(软删除)
--delete-after 先传输,传输结束后再删目标文件(默认策略
--delete-before 先删目标文件再传输
--delete-during 在传输过程中边比较边删除
--fix-case 强制把大小写不敏感目标端上命名不一致的文件重命名以匹配源端
--ignore-errors 即便存在 I/O 错误也继续执行删除
--list-cutoff int 目录清单超过该阈值时落盘排序以节省内存(默认 1000000)
--max-delete int 单次同步最多删除的文件数(默认 -1 即不限)
--max-delete-size SizeSuffix 单次同步删除的总字节上限(默认 off)
--suffix string 给被修改的文件加后缀后再写入(结合 --backup-dir 使用)
--suffix-keep-extension 使用 --suffix 时保留原扩展名
--track-renames 追踪文件重命名,若能服务端 move 则直接改名,不重新传输
--track-renames-strategy string 追踪重命名使用的策略 hash|modtime|leaf(默认 hash

三种删除模式是如何实现的

fs/sync/sync.gorunSyncCopyMove 可以看到三种模式对应着完全不同的执行流程:

  • --delete-before:先额外执行一遍"只删不传"(DeleteModeOnly)的 pass,全部删除完成后,再以 DeleteModeOff(纯复制)跑第二遍传输。因此 --delete-before 无法与 --track-renames 联用,源码中直接报 can't use --delete-before with --track-renames
  • --delete-duringDstOnly 回调在 marching 遍历中遇到目标独有对象时,直接把对象送入 deleteFilesCh 边遍历边删(见 sync.go);
  • --delete-after(默认):marching 阶段只把目标独有对象记入 dstFiles map,全部比对与传输结束后,在 run() 收尾统一执行 deleteFiles(false),此时若存在任何未处理错误便放弃删除(对应 sync.go)。

三种模式只能同时启用一个fs/config/configflags/configflags.go 中做了互斥检查,见 configflags.go)。测试代码 fs/sync/sync_test.go 亦验证了默认值确实是 DeleteModeAfter

性能与安全取舍--delete-before 先在目标端清场,可显著减少并发比对压力,但"先删后传"的窗口期数据不安全;--delete-after 最安全(出错可全部保留)但目标端需暂存待删清单;--delete-during 处于两者之间,属于吞吐与安全的中庸选项。

备份与软删除:--backup-dir / --suffix

--backup-dir 可以把被覆盖与被删除的对象先"挪进"另一个目录结构,实现同步前的软删除:

# 把被替换/删除的文件都留档到 remote:trash,按原路径层级存放
rclone sync /data remote:backup --backup-dir remote:trash

# 同时加后缀,进一步避免覆盖旧版本
rclone sync /data remote:backup --backup-dir remote:trash --suffix .bak --suffix-keep-extension

--track-renames:改名不重传

当大量文件只是改了名字(典型如轮转日志、重命名的媒体库),配合 --track-renames 可让 rclone 依据 hash(默认)/modtime/leaf 策略猜测源端新名与目标端旧名的对应关系,从而走服务端 move 而非整文件重传;源码中通过 makeRenameMap() 按哈希建索引,并在 marching 结束后把"源端无匹配"的文件送入 rename 管道尝试服务端改名(见 sync.go)。重命名追踪会占用较多内存与哈希计算,适合源端文件大而批量改名场景。

Important Options 与 Filter Options

三个最重要的通用标志

选项 说明
-n, --dry-run 试运行,不产生任何永久变更(首次使用 sync 必加
-i, --interactive 交互模式,每个删除/覆盖前逐一确认
-v, --verbose count 输出更多日志(可重复叠加)

其中 --dry-run--interactive 正是官方针对"sync 可能造成数据丢失"给出的第一道防线。

过滤选项:控制同步的边界

选项 说明
--delete-excluded 删除目标端上"被排除规则挡掉"的文件
--exclude stringArray 排除匹配 pattern 的文件
--exclude-from stringArray 从文件中读取排除规则(- 表示从 stdin 读取)
--exclude-if-present stringArray 若目录中存在指定文件名则排除整个目录
--files-from stringArray 从文件中读取"要同步的源文件名列表"(- 表示 stdin)
--files-from-raw stringArray 逐行原样读取源文件名单,不做任何行处理(- 表示 stdin)
--files-from0 stringArray 以 NUL 字符作为分隔符的名单文件(- 表示 stdin)
-f, --filter stringArray 添加一条过滤规则
--filter-from stringArray 从文件读取过滤规则(- 表示 stdin)
--hash-filter string k/n 或随机 @/n 划分文件名
--ignore-case 过滤时忽略大小写
--include stringArray 包含匹配 pattern 的文件
--include-from stringArray 从文件读取包含规则(- 表示 stdin)
--max-age Duration 只传输比该时间更"年轻"的文件(sms/s/m/h/d/w/M/y 后缀,默认 off)
--max-depth int 限制递归深度(默认 -1 不限)
--max-size SizeSuffix 只传输小于该大小的文件(B/K/M/G/T/P 后缀,默认 off)
--metadata-exclude stringArray 按 metadata 模式排除
--metadata-exclude-from stringArray 从文件读取 metadata 排除规则
--metadata-filter stringArray 添加 metadata 过滤规则
--metadata-filter-from stringArray 从文件读取 metadata 过滤规则
--metadata-include stringArray 按 metadata 模式包含
--metadata-include-from stringArray 从文件读取 metadata 包含规则
--min-age Duration 只传输比该时间更"年长"的文件(默认 off)
--min-size SizeSuffix 只传输大于该大小的文件(默认 off)

注意默认情况下被排除的文件不会被删除;只有加上 --delete-excluded 后,"目标端存在但被规则排除"的文件才会被一并清理。

Listing Options

选项 说明
--default-time Time 当文件/目录 modtime 未知时显示的时间(默认 2000-01-01T00:00:00Z
--fast-list 后端支持时用递归列举(省事务但耗内存)

一次安全同步的完整工作流

把上述知识点串联成可落地的操作流:

# 第 1 步:先试运行,看清将要发生什么(尤其将被删除的文件)
rclone sync --dry-run -v /data remote:backup

# 第 2 步:把"将删除/将覆盖"的清单留档,人工复核
rclone sync --combined - --dry-run /data remote:backup
rclone sync --missing-on-src to_delete.txt --dry-run /data remote:backup

# 第 3 步:交互式执行(逐个确认删除),同时留备份
rclone sync -i --backup-dir remote:trash --suffix .old /data remote:backup

# 第 4 步:核对结果——对比差异应变为空
rclone check /data remote:backup

从源码看 sync 的实现骨架

rclone sync 命令本身很薄(见 cmd/sync/sync.go),真正的同步引擎在 fs/sync/sync.gosyncCopyMove 结构体中。其核心是一条多阶段流水线

  1. 重叠检测newSyncCopyMove 先做 overlapping 检查(ErrorOverlapping);
  2. marching 双向遍历:借助 fs/march 模块同时遍历源与目标,回调(PairDstOnlySrcOnlyDir)把对象按角色分流:
    • 相同对象 → 可跳过或进入 checker;
    • 仅源有 → 进入 toBeUploaded 传输管道;
    • 仅目标有 → 按删除模式记入 dstFiles 或直接进入删除管道;
  3. checker/transfers 并发管道:checker 先比对,transfer 再并发上传,--check-first 则把"先全部比对"拆成显式阶段(对应 Checks finished, now starting transfers 日志,见 sync.go);
  4. 收尾:按 --delete-after 批量删除、目录 modtime 延迟回写、空目录裁剪,并汇总错误决定最终退出码。

这样一套"先比较、再传输、最后清理"的顺序,正是 sync 能既高效(跳过相同文件)又相对安全(出错即停删)的底层原因。更多并发细节可继续阅读 fs/sync/sync.gofs/sync/sync_test.go;各同步选项的默认值均可通过 全局 flags 文档 查阅。

参见

登录后查看全文
热门项目推荐
相关项目推荐