diff 默认只显示行级差异,不标出同一行内字符变化;需用 -u 配合 diff-highlight、git diff --word-diff 或 xxd 转换后比较;二进制文件应使用 cmp 或 sha256sum 判断异同。

diff 命令默认只显示行差异,不显示具体字符变化
你用 diff file1.txt file2.txt 看到的只是哪些行增删了,但同一行里只改了一个字母(比如 cat → car),它不会标出 t 变成了 r。这是默认行为,不是 bug。
想看到字符级差异,得加 -u(统一格式)配合 colordiff 或用 git diff --no-index:
git diff --no-index --word-diff=plain file1.txt file2.txt
注意:--word-diff 在老版本 Git 里不支持 --no-index,Git 2.9+ 才稳定可用。
- 纯命令行环境没装 Git?用
diff -u file1.txt file2.txt | diff-highlight(需先apt install diff-highlight或从 git 源码里复制脚本) -
diff -y(并排模式)看着直观,但遇到长行会自动换行,导致对齐错乱,别在自动化脚本里用 - 空格变化默认被忽略——除非加
-b(忽略空白符)或-w(更激进地忽略所有空白),否则hello<space></space>和hello会被当成两行不同
二进制文件直接 diff 会提示 “Binary files differ” 就停住
diff 对非文本文件非常保守:只要文件头有零字节或检测到 NUL 字符,就放弃逐行比较,直接输出 Binary files a and b differ。它不报错,也不继续——这容易让人误以为“没差异”,其实只是没告诉你。
真要比较二进制文件是否完全一致,用 cmp 更准:
cmp -l file1.bin file2.bin | head -20
cmp -l 会列出所有字节不同的位置和值(八进制),head 是防止刷屏。如果完全一样,就什么也不输出。
- MD5/SHA 校验适合快速判断是否相同,但无法定位差异位置:
sha256sum file1.bin file2.bin - 想看二进制 diff 的“可读形式”?
xxd file1.bin | diff -u - ,但大文件会很慢,内存占用高 -
diff --brief(即-q)能安静判断是否相同,输出只有“Files a and b differ”或无输出,适合写进 shell 判断逻辑
递归比较目录时,-r 不等于 “智能同步”
diff -r dir1 dir2 是逐个文件调用 diff,但它完全不管软链接指向、文件权限、修改时间、SELinux 上下文这些元数据。两个目录内容一致,但一个里 script.sh 是 755,另一个是 644,diff -r 仍显示“no difference”。
如果你实际想确认“能不能 rsync 过去不出错”,光靠 diff -r 不够:
- 权限/属主差异:用
diff ,但注意路径顺序和排序稳定性 - 忽略特定文件:加
--exclude='*.log'或--exclude-dir='.git',否则可能卡在 node_modules 里 -
diff -r遇到只在一个目录存在的子目录,会直接报Only in dir1: xxx,但不会递归进那个目录再比——这是设计如此,不是漏了
diff 输出里 “12a13,15” 这类标记怎么读
这是 ed 编辑器风格地址标记,现在看着反直觉,但理解后查问题很快。以 12a13,15 为例:
-
12:原文件第 12 行 -
a:append(在它后面添加) -
13,15:目标文件第 13 到 15 行的内容
也就是说:要在原文件第 12 行之后插入目标文件的 13–15 行。类似地,5c5,6 表示“把原文件第 5 行改成目标文件第 5–6 行”。
新手常误以为数字是“差异行号”,其实左边是原文件上下文,右边是目标文件上下文,中间字母含义固定:a=add,d=delete,c=change。
真正在脚本里解析这个格式?别自己手撕——用 diff -u 输出,然后交给 patch 或 Python 的 difflib 处理,人眼友好得多。
最常被忽略的是:diff 默认不保证输出顺序绝对稳定。如果两个文件都有多处小修改,不同 locale 下排序可能微变,做自动化比对前记得设 LC_ALL=C diff ...。










