diff 是什么
diff 逐行比较两个文件,输出把前者变成后者需要做的增删改;加上 -u 会输出统一格式(unified diff),这正是补丁与代码评审里看到的格式。它的价值不只是「看哪里不一样」,更在于把差异变成可复核、可传递、可回滚的文本:配置巡检、发布核对、变更审计都依赖它。比较目录时用 -r 递归,配合 -q 只看结论,就能在几分钟内确认两台机器的配置是否一致。
基本信息
| 适用平台 | Linux、macOS、BSD(GNU diffutils / BSD diff);--color、-y 并排输出等为 GNU 常见扩展 |
|---|---|
| 命令语法 | diff [选项] 文件1 文件2;比较目录时同样语法 |
| 常用选项 | -u 统一格式、-c 上下文格式、-q 只报告是否不同、-r 递归比较目录、-N 把缺失文件视为空文件、-w 忽略空白、-i 忽略大小写、-y 并排显示、--strip-trailing-cr 忽略行尾差异 |
| 退出码 | 0 表示无差异、1 表示有差异、2 表示出错;这是 diff 在脚本中最常用的判断方式 |
| 相关工具 | cmp 做二进制逐字节比较、sha256sum 做整体校验、patch 应用差异、vimdiff 与 git diff 提供更友好的查看方式 |
典型使用场景
- 配置巡检:比较当前配置与基线备份,确认是否被手工改动过
- 发布核对:比较新旧版本目录,确认变更范围符合预期
- 生成补丁:-u 输出可直接交给 patch 或进入代码评审流程
- 快速判断是否相同:-q 配合退出码,适合在大批量文件上做筛查
- 排查格式问题:先用 -w 忽略空白,若差异消失说明只是缩进或空格问题
- 跨平台文件比对:用 --strip-trailing-cr 消除 Windows 与 Linux 行尾差异带来的假差异
常用示例
常用示例
diff app.conf app.conf.bak # 普通格式
diff -u app.conf.old app.conf # 统一格式(补丁用)
diff -q a.txt b.txt # 只报告是否不同
diff -r --brief /etc/app /data/app # 目录递归、只看结论
diff -w a b # 忽略空白差异
diff -u old/ new/ > change.patch # 生成补丁,可交给 patch 应用
diff -y --width=120 a b # 并排显示,便于人工比对
diff --strip-trailing-cr win.txt linux.txt
if diff -q a b >/dev/null; then echo same; else echo differ; fi差异标记读法
| 标记 | 含义 | 对应操作 |
|---|---|---|
| a | 在第一个文件里新增内容才与第二个一致 | 第一个文件缺少这些行 |
| d | 删除第一个文件里的内容 | 第一个文件多出这些行 |
| c | 修改,第一个文件里的这段要换成新内容 | 最常见的差异类型 |
| < 开头 | 来自第一个文件的行 | 旧内容 |
| > 开头 | 来自第二个文件的行 | 新内容 |
| Only in 目录 | 该目录独有的文件(比较目录时) | 用 -N 可把缺失视为空文件 |
先比整体再比细节是高效做法:两个文件的 sha256sum 相同就直接跳过,不同再用 cmp 找出首个差异位置(大文件上比逐行 diff 快得多),确认确实需要看内容差异时再用 diff。对目录做批量巡检时,先 diff -rq 拿到文件清单,再对重点关注的文件逐个细看。
常见假差异的成因:Windows 的 CRLF 与 Linux 的 LF、行尾多余空格、制表符与空格混用。对应处理是 --strip-trailing-cr、-w 与 -b(忽略空白数量变化)。排查「配置明明一样却不同」时,先加这些参数确认差异是否只是格式问题。
用 diff 生成的补丁应用到生产配置前,要在测试环境验证并保留原文件备份:路径前缀(-p 参数)与实际目录不一致会导致补丁修改错文件,部分应用也可能出现失败后留下半改状态的配置。