rclone check 命令完全指南:云端与本地文件一致性校验的原理与实战
rclone check 是 rclone 提供的“只读校验”命令,用于对比源与目标两端目录中的文件在大小与哈希上是否一致,并输出一份差异报告;它不会对两端做任何增删改。本指南以 docs/content/commands/rclone_check.md 为骨架,结合 cmd/check/ 与 fs/operations/ 的源码实现,帮你彻底掌握:何时该用 check、--size-only / --download / --checkfile / --one-way 各解决什么问题,以及 --combined、--differ 等报告选项如何配合脚本自动化做“云端数据巡检”。读完你将能够把 rclone 的校验能力落地到备份验证、迁移后核对、定时数据完整性扫描等实战场景。
命令概览与基本用法
rclone check 的职责一句话即可概括:检查源端与目标端的文件是否匹配。它在两棵目录树上同时遍历同名文件,逐一对比大小与哈希(MD5 或 SHA1 等),把不匹配的文件记录到报告中;整个过程不会修改源或目标上的任何文件。
命令格式如下:
rclone check source:path dest:path [flags]
最基本的用法是给出两个远程(或本地路径与远程的组合):
# 对比本地目录与云端远程目录
rclone check /home/user/backup remote:backup
# 对比两个不同云存储上的目录
rclone check gdrive:docs s3:docs-archive
运行结束后,rclone 会在日志里汇总统计信息,例如“发现了 N 处差异”“N 个匹配文件”等。核心入口定义在 cmd/check/check.go:RunE 先通过 cmd.CheckArgs(2, 2, ...) 强制要求恰好两个位置参数(source:path 与 dest:path),随后在闭包中调用底层实现 operations.Check。
在继续之前,先完整列出本命令专属的选项表(对应文档 Options 小节):
-C, --checkfile string Treat source:path as a SUM file with hashes of given type
--combined string Make a combined report of changes to this file
--differ string Report all non-matching files to this file
--download Check by downloading rather than with hash
--error string Report all files with errors (hashing or reading) to this file
-h, --help help for check
--match string Report all matching files to this file
--missing-on-dst string Report all files missing from the destination to this file
--missing-on-src string Report all files missing from the source to this file
--one-way Check one way only, source files must exist on remote
这些专属 flag 的绑定与默认值可在 cmd/check/check.go 中看到:例如 --download、--one-way 为布尔开关,--combined、--differ、--match 等则接收一个“输出文件名”字符串参数(值为 - 时表示写到 stdout,这一点后文会细讲)。
校验原理:大小 + 公共哈希的双重对比
check 的默认判断流程是“先比大小、再比哈希”,逐层递进:
-
大小对比:对于两端都存在的同名文件,若大小不一致,直接判定“sizes differ”(差异)。底层逻辑在 fs/operations/operations.go 的
sizeDiffers函数中,它还会尊重全局的--ignore-size配置以及文件大小未知(< 0)的情形。 -
哈希对比:大小相同后,通过
CheckHashes比较两端哈希。fs/operations/operations.go 中的实现先取src.Fs().Hashes().Overlap(dst.Fs().Hashes()),即两端远程都支持的哈希类型的交集,再从交集中任取一种进行比较——这就是为什么文档 Synopsis 中表述为“比较大小和哈希(MD5 或 SHA1)”:在大多数组合里,实际生效的是交集里这一种公共哈希。文档级命令入口在 cmd/check/check.go 中会先算出该公共哈希并打印提示:- 若两端存在公共哈希,日志显示
Using <hash> for hash comparisons; - 若交集中没有任何哈希(例如某后端本身不支持哈希),则警告
No common hash found - not using a hash for checks,此时哈希检查无法进行,同名且同大小的文件会被视为“无法检查哈希”而放行。
- 若两端存在公共哈希,日志显示
真正把“两棵树”同步遍历并回调的骨架是 fs/operations/check.go 的 CheckFn:它复用与 sync/copy 相同的 march 遍历机制(march.March,见 fs/march 目录),在遍历过程中回调 DstOnly、SrcOnly、Match 三个状态分支,并用 atomic 计数器累计 differences、matches、noHashes 等统计量。也就是说,check 与 copy/sync 共享同一套“目录同步行走”框架,只是它的回调只做比对、不做写入——这正是“不修改源和目标”这一承诺的来源。
快速核对:--size-only
文档明确指出:如果加上 --size-only 标志,将只比较大小而不比较哈希,适合做“快速检查”(Use this for a quick check)。
rclone check gdrive:docs s3:docs-archive --size-only
适合的场景包括:你已经知道两侧哈希体系不可用、文件不会发生“等大小但内容被篡改”的情形、或只是想先粗筛一遍做巡检。源码层面,该开关由全局配置 size_only 控制(默认 false,注册于 fs/config.go),在 fs/operations/check.go 的 checkIdentical 中生效:一旦开启,大小比较通过后就直接返回“相同”,不再调用哈希检查函数。对应的单元测试见 fs/operations/check_test.go 的 TestCheckSizeOnly。
逐字节核验:--download
对于不支持哈希的远程,或当你希望真正校验“每一个字节”时,使用 --download 标志。文档对它的定位是:
会同时下载两端的数据,并“on the fly”地相互比对。这适用于不支持哈希的远程,或者你真的想把所有数据都校验一遍的场景。
# 对不支持哈希的后端做真正的逐字节核验
rclone check ftp:files remote:files --download
从实现上看,cmd/check/check.go 在检测到 --download 时直接改走 operations.CheckDownload,而它(见 fs/operations/check.go)把每个文件的比对函数替换为“同时打开两端流、边下载边比对”。流的实际比较由 CheckEqualReaders 完成:以 64 KiB 为缓冲分块读取双方数据流,逐块用 bytes.Equal 比对,一旦长度或内容不一致即判定不同,直到双方都读到 EOF 才算完全相同。比对过程会分别计入两端的 accounting 传输统计,因此 --download 会真实消耗下载流量,代价明显高于纯哈希比对——这也是文档建议“只在哈希不可用或确实想全量校验”时才使用它的原因。相应的端到端测试包括 fs/operations/check_test.go 的 TestCheckDownload。
单向检查:--one-way
默认情况下,check 是“双向”的:源端有而目标端没有、以及目标端有而源端没有的文件都会被记录为差异。如果你只想确认“源里的文件在目标端都存在且一致”,而不关心目标端额外多了什么文件,则加 --one-way:
rclone check local:data remote:backup --one-way
文档对此的解释很直接:--one-way 只检查源端文件在目标端是否匹配,反方向不检查,因此“目标端比源端多出的额外文件不会被发现”。在 fs/operations/check.go 的 DstOnly 回调中可以看到:当 opt.OneWay 为真时,遇到“仅目标端存在”的对象会直接跳过(return false),不再计入 missing-on-src。
典型的用途是把校验语义收窄为“备份是否完整覆盖了源数据”,而不是“两端目录是否完全镜像”。
对照校验和文件:--checkfile 与 SUM 格式
--checkfile HASH 是一个很有意思的能力:当你指定一个合法哈希名(如 md5、sha1、crc32)后,source:path 不再被当作目录,而是被解读为一个文本格式的 SUM 校验文件,命令转而校验“目标端文件是否与该 SUM 文件里记录的哈希一致”。
# 让 source:path 指向本地 md5 校验文件,dest:path 指向要核对的远程目录
rclone check -C md5 sums.md5 remote:data
SUM 文件每行的通用格式为:
<十六进制哈希> <空格或星号> <文件路径>
即形如 d41d8cd98f00b204e9800998ecf8427e path/to/file(文本模式用空格,二进制模式习惯用 *,两者均被接受)。SUM 文件中的哈希值按大小写不敏感处理,rclone 内部统一转成小写。这种解析规则可以在 fs/operations/check.go 的 ParseSumFile 中看到精确实现:它按行读取,用正则 ^([^ ]+) *$ 拆分“哈希”与“文件名”,对格式错误的行只给出最多前 3 条警告,并把“重复文件”的条目忽略。这样一份 SUM 文件可直接由配套命令生成:
- rclone hashsum 负责“产出”哈希清单;
- 校验侧除了本命令的
--checkfile,还有 rclone checksum 专门“用 SUM 文件核对目标端”,它把 sumfile 视为源、dst:path视为目标,语义与此处完全一致,两者共享同一套check专用 flags(见 cmd/checksum/checksum.go)。
在 --checkfile 分支下,cmd/check/check.go 先用 hashType.Set(checkFileHashType) 校验哈希名是否合法(不合法时打印 hash.HelpString(0) 列出所有可用哈希),再通过 cmd.NewFsSrcFileDst(args) 把第一个参数切分为“SUM 文件所在的文件系统 + 文件名”,最后调用 operations.CheckSum。CheckSum 还会做两件值得注意的事:
- 若目标文件系统根本不支持该哈希类型(且未开
--download),会直接报错hash type is not supported by file system; - 遍历完目标目录后,SUM 文件中“未被任何目标文件消费”的条目会被判为
missing-on-dst(文件中多出来、云端不存在的哈希),使用+前缀报告——这正好与rclone hashsum+rclone check -C形成“生成清单→核对清单”的闭环。
--checkfile 也可配合 --download:此时不再依赖远程的存储哈希,而是把目标文件下载下来即时计算哈希与 SUM 文件比对,对应 CheckSum 中 download 分支的逻辑。相关测试见 fs/operations/check_test.go(TestCheckSum / TestCheckSumDownload)。
报告输出:--differ / --match / --missing-* / --error 与 --combined
check 的一大亮点是可以把结果结构化导出,便于二次处理或归档。文档规定了如下五类报告 flag,每个都接收一个文件路径参数(或写 - 表示输出到标准输出 stdout):
--differ:两侧都存在、但内容(大小或哈希)不一致的文件路径,每行一条;--missing-on-dst:只在源端存在(目标端缺失)的文件路径;--missing-on-src:只在目标端存在(源端缺失)的文件路径;--match:两侧都存在且完全匹配的文件路径;--error:读取或计算哈希时出错的文件路径。
例如只把“两端不一致”的文件列到 stdout:
rclone check gdrive:docs s3:docs-archive --differ -
输出文件的打开与关闭逻辑集中在 cmd/check/check.go 的 GetCheckOpt:空字符串表示“不启用该项”,- 映射到 os.Stdout,其余情况用 os.Create 创建真实文件,并在命令结束时统一关闭。
而 --combined 则把所有结果合并写到一个文件(或 stdout),每行形如“一个符号 + 空格 + 路径”,风格类似 diff 输出。五种符号的含义如下表:
| 符号 | 含义 |
|---|---|
= path |
该路径在源与目标中都存在,且完全相同 |
- path |
该路径在源端缺失,只存在于目标端 |
+ path |
该路径在目标端缺失,只存在于源端 |
* path |
该路径在源与目标中都存在,但内容不同 |
! path |
读取或哈希源/目标时出现错误 |
rclone check gdrive:docs s3:docs-archive --combined combined.txt
在实现层,fs/operations/check.go 的 report/reportFilename 承担所有落盘逻辑:每条路径先按需写入对应分类输出(differ/match/error/missing-on-*),若设置了 combined 则统一再追加一行带符号的记录。符号与分类的对应关系就发生在 DstOnly(-)、SrcOnly(+)、Match 中 differ 分支(*)、匹配分支(=)以及错误分支(!)。类别不匹配(如一边是文件、另一边是同名目录)也会被合理归类,例如源为目录而目标为文件时,该条目会按目标端缺失处理。
结果统计、退出码与并发控制
每次执行结束,check 会在日志中汇总统计信息。汇总逻辑位于 fs/operations/check.go 的 reportResults,可输出的统计包括:
- 源端/目标端缺失文件数(
N files missing;在 SUM 校验场景,源的“缺失实体”措辞变为N hashes missing); - 发现的差异总数(
N differences found); - 检查过程中的错误数(
N errors while checking); - 无法检查哈希的数量(
N hashes could not be checked); - 匹配文件数(
N matching files)。
只要发现任何差异,命令最终都会返回一个错误(%d differences found),因此 check 的退出码适合作为 CI/CD 或定时脚本的判定依据——脚本可直接用 rclone check ... && echo "OK" 这类写法对一致性做门禁判断。
并发方面,文档明确说明默认并行校验数为 8(The default number of parallel checks is 8),对应全局选项 --checkers。默认值定义在 fs/config.go,归入 Performance 分组;在 fs/operations/check.go 中,CheckFn 用一个容量为 ci.Checkers 的 token channel(tokens: make(chan struct{}, ci.Checkers))来限制同时进行的哈希/下载检查协程数。对“文件数量巨大但单个文件很小”的校验场景,适当调高 --checkers 能显著缩短总耗时;反向地,为了不压垮弱网环境,也可以调低。并发限流行为本身也有专门测试覆盖,例如 fs/operations/check_test.go 中验证“哈希/下载确实以 --checkers 指定的并发数在跑”。
crypt 加密远程的特殊处理:cryptcheck
普通 rclone check 对 crypt 远程 是不适用的——因为 crypt 在云端看到的是加密后的对象,哈希也是加密层的哈希,与明文文件并无可比性。因此文档明确指出:对于 crypt 远程,有专门的命令 rclone cryptcheck(详见 docs/content/commands/rclone_cryptcheck.md),它能够直接校验加密文件的校验和(在不解密或仅做必要解密的基础上核对明文哈希)。当你把源或目标配成 crypt: 远程时,请优先查阅并使用 cryptcheck,而非普通 check。
与 check 共享的通用选项
check 并非孤立命令,它与其他目录类命令共享三类选项。以下表格完整保留了文档中的相关片段,方便你在实际拼装命令时查阅。
Check Options(check 类命令共享)
--max-backlog int Maximum number of objects in sync or check backlog (default 10000)
--max-backlog 限制同步/校验过程中排队等待处理的最大对象数(默认 10000),它主要用于防止海量小文件场景下内存中的待处理队列无限膨胀。
Filter Options(目录过滤)
--delete-excluded Delete files on dest excluded from sync
--exclude stringArray Exclude files matching pattern
--exclude-from stringArray Read file exclude patterns from file (use - to read from stdin)
--exclude-if-present stringArray Exclude directories if filename is present
--files-from stringArray Read list of source-file names from file (use - to read from stdin)
--files-from-raw stringArray Read list of source-file names from file without any processing of lines (use - to read from stdin)
--files-from0 stringArray Read list of source-file names from file using NUL as separator (use - to read from stdin)
-f, --filter stringArray Add a file filtering rule
--filter-from stringArray Read file filtering patterns from a file (use - to read from stdin)
--hash-filter string Partition filenames by hash k/n or randomly @/n
--ignore-case Ignore case in filters (case insensitive)
--include stringArray Include files matching pattern
--include-from stringArray Read file include patterns from file (use - to read from stdin)
--max-age Duration Only transfer files younger than this in s or suffix ms|s|m|h|d|w|M|y (default off)
--max-depth int If set limits the recursion depth to this (default -1)
--max-size SizeSuffix Only transfer files bigger than this in KiB or suffix B|K|M|G|T|P (default off)
--metadata-exclude stringArray Exclude metadatas matching pattern
--metadata-exclude-from stringArray Read metadata exclude patterns from file (use - to read from stdin)
--metadata-filter stringArray Add a metadata filtering rule
--metadata-filter-from stringArray Read metadata filtering patterns from a file (use - to read from stdin)
--metadata-include stringArray Include metadatas matching pattern
--metadata-include-from stringArray Read metadata include patterns from file (use - to read from stdin)
--min-age Duration Only transfer files older than this in s or suffix ms|s|m|h|d|w|M|y (default off)
--min-size SizeSuffix Only transfer files bigger than this in KiB or suffix B|K|M|G|T|P (default off)
利用这些过滤参数可以精确控制“到底校验哪些文件”,例如 rclone check src dst --exclude "*.tmp" 可以把临时文件排除在校验范围之外;与 --checkfile 组合时,过滤掉的文件对应地也不会被计入“SUM 文件中未消费条目”的缺失统计(见 fs/operations/check.go 中通过 filter.GetConfig 过滤判断的逻辑)。
Listing Options(目录遍历)
--default-time Time Time to show if modtime is unknown for files and directories (default 2000-01-01T00:00:00Z)
--fast-list Use recursive list if available; uses more memory but fewer transactions
其中 --fast-list 在目标后端支持递归列举(如 S3、GCS 等)时使用,通过牺牲一定内存换取更少的 API 调用次数,对云存储 API 配额紧张的账号尤其有用。
实战组合:把 check 变成你的数据巡检工具
把上述选项串起来,可以得到几类高价值用法:
1. 迁移/备份后的完整性验收
rclone check local:data remote:backup --combined backup-report.txt
若无 */+/- 行且退出码为 0,即可认定备份完整一致。
2. 只关心源是否被完整覆盖的单向巡检
rclone check local:data remote:backup --one-way --differ - --missing-on-dst -
任何差异都会逐行打到 stdout,适合接入 cron 后配合邮件/告警。
3. 对不支持哈希的远程做全量字节校验
rclone check webdav:media sftp:media --download --checkers 16
--download 兜底一切哈希不可用的情况,--checkers 提升并发以缩短全量比对时长。
4. 用哈希清单做离线/跨周期校验
# 先在生产端生成清单
rclone hashsum MD5 remote:data > data.md5
# 后续随时用清单核验任意副本
rclone check -C md5 data.md5 remote:data-copy
综上,rclone check 本质上是把 sync 的遍历引擎改造成“零写入的比对器”,配合 --size-only(快)、--download(全量逐字节)、--checkfile(清单核对)、--one-way(单向)四种模式以及 --combined/--differ 等结构化报告输出,几乎可以覆盖云存储数据一致性核验的全部场景。其命令入口与底层比对逻辑分别维护在 cmd/check/check.go 与 fs/operations/check.go,全套行为均有 fs/operations/check_test.go 中的测试用例支撑,值得在深入定制前仔细研读。
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 StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00