必须加 -u 才能看清改了什么、上下文在哪,因为默认格式用 2c2、5a6 等符号标记变化,无上下文且难理解,而 -u 格式自动显示前后各3行上下文并用±标识增删。

直接用 diff 就行,但默认输出难读,必须加 -u 才能看清改了什么、上下文在哪。
为什么 diff file1 file2 输出看不懂?
原始输出用 2c2、5a6 这类符号标记变化类型和行号,比如:
2c2 there
这种格式对机器友好,但人眼需要反应几秒才能理解“第2行被替换了”。更麻烦的是它不显示上下文——你不知道这行前面是啥、后面是啥,容易误判是否真有逻辑差异。
-
-u(统一格式)会自动带出前后各3行上下文,一眼看出改动位置 - 不加
-u时,哪怕只改了一个字母,你也得手动翻文件去定位 - 很多工具(如
git apply、CI 流水线)只认-u格式输出
diff -u 的实际输出长什么样?
执行 diff -u a.txt b.txt 后,你会看到类似:
--- a.txt 2026-10-01 14:22:03.000000000 +0800 +++ b.txt 2026-10-01 14:22:11.000000000 +0800 @@ -1,4 +1,4 @@ 1. apple -2. banana +2. orange 3. cherry 4. mango
关键点:
-
---和+++行标出文件名与时间戳(可忽略) -
@@ -1,4 +1,4 @@表示:a.txt 从第1行起共4行,b.txt 对应区域也是4行 -
-开头是 a.txt 里删掉的行,+开头是 b.txt 里新增的行 - 没带符号的行(如
1. apple)是共同上下文,帮你锚定位置
常见干扰怎么过滤?
配置文件、日志或自动生成文本常因空格、大小写、行序导致假差异,别硬扛,直接用对应选项:
- 忽略所有空白字符(空格、制表符、换行符差异):
diff -uw file1 file2 - 忽略大小写:
diff -ui file1 file2(注意-i是 ignore-case,不是 input) - 忽略行顺序(比如两个 JSON 数组字段顺序不同):
diff ,靠 Bash 进程替换避免生成临时文件 - 只看是否不同,不关心怎么不同:
diff -q file1 file2,返回码 0=相同,1=不同,适合脚本判断
大文件或目录对比要注意什么?
diff 默认加载全文件进内存,遇到几百 MB 的日志或二进制文件会卡死甚至 OOM:
- 纯文本大文件先用
head/tail截取关键段再比:diff - 比目录必须加
-r:diff -r dir1 dir2,否则只比目录本身(永远“相同”) - 目录比对时加
-q或grep过滤,不然输出全是“Files dir1/a and dir2/a differ”,根本找不到重点:diff -rq dir1 dir2 | grep -E "Only|differ" - 二进制文件别用
diff—— 改用cmp:cmp file1.bin file2.bin,它只报第一个字节差异位置
真正容易被忽略的是行尾符(CRLF vs LF)和不可见字符。如果 diff -u 显示整行都不同,但肉眼看不出区别,先运行 file file1 file2 看编码/行尾,再用 xxd file1 | head 检查末尾字节。











