rclone sync 命令完全指南:安全同步、删除策略与变更报告
rclone sync 是 rclone 家族中最常用的命令之一,它的职责是"让源与目标变得完全一致,并且只修改目标端"。本指南围绕官方命令文档 rclone_sync.md 展开,结合 cmd/sync/sync.go 与 fs/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)。
不过官方提供两条变通路径:
- 用 filter 规则在同步中排除掉目标所在位置;
- 在目标目录内放置一个
exclude-if-present标记文件(如.rclone-exclude),再同步到"位于源目录内部的目标目录"。该场景下结合--exclude-if-present即可实现自包含的增量更新。
修改时间与元数据同步
- 只要后端支持,rclone 会尽力同步文件和目录的修改时间;
- 目录修改时间的同步条件相当苛刻(后端需支持空目录/目录 modtime 写入),源码中由
setDirModTime、setDirModTimeAfter等状态位控制,见 sync.go; - 若需要同步文件的自定义元数据(Metadata),必须显式加
--metadata/-M,并保证两端后端都具备读写元数据能力; - 若同时希望空目录也被搬运到目标端,需要加
--create-empty-src-dirs(rclone 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.go 的 ConfigureLoggers 中做了显式提示。每个文件都是在执行过程中被记录的(而非结束后统一统计),所以报告更适合用来预测与审计,而不是作为最终交割凭据。
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.go 的 runSyncCopyMove 可以看到三种模式对应着完全不同的执行流程:
--delete-before:先额外执行一遍"只删不传"(DeleteModeOnly)的 pass,全部删除完成后,再以DeleteModeOff(纯复制)跑第二遍传输。因此--delete-before无法与--track-renames联用,源码中直接报can't use --delete-before with --track-renames;--delete-during:DstOnly回调在 marching 遍历中遇到目标独有对象时,直接把对象送入deleteFilesCh边遍历边删(见 sync.go);--delete-after(默认):marching 阶段只把目标独有对象记入dstFilesmap,全部比对与传输结束后,在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 |
只传输比该时间更"年轻"的文件(s 或 ms/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.go 的 syncCopyMove 结构体中。其核心是一条多阶段流水线:
- 重叠检测:
newSyncCopyMove先做 overlapping 检查(ErrorOverlapping); - marching 双向遍历:借助 fs/march 模块同时遍历源与目标,回调(
Pair、DstOnly、SrcOnly、Dir)把对象按角色分流:- 相同对象 → 可跳过或进入 checker;
- 仅源有 → 进入
toBeUploaded传输管道; - 仅目标有 → 按删除模式记入
dstFiles或直接进入删除管道;
- checker/transfers 并发管道:checker 先比对,transfer 再并发上传,
--check-first则把"先全部比对"拆成显式阶段(对应Checks finished, now starting transfers日志,见 sync.go); - 收尾:按
--delete-after批量删除、目录 modtime 延迟回写、空目录裁剪,并汇总错误决定最终退出码。
这样一套"先比较、再传输、最后清理"的顺序,正是 sync 能既高效(跳过相同文件)又相对安全(出错即停删)的底层原因。更多并发细节可继续阅读 fs/sync/sync.go 与 fs/sync/sync_test.go;各同步选项的默认值均可通过 全局 flags 文档 查阅。
参见
- 该命令文档的自动生成源头:cmd/sync/sync.go
- 同步引擎实现:fs/sync/sync.go
- 同步标志注册与解析:fs/config/configflags/configflags.go
- Logger Flags 实现:fs/operations/operationsflags/operationsflags.go
- 关联命令:rclone copy、rclone dedupe、rclone lsf
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00