原文在 2009/04/17 发表于 http://unix.worldiswelcome.com/understanding-the-diff-command-in-unix
Unix 系统管理员来经常需要去知道两个文件之间有什么差异. diff
命令就是干这个的. 我现在就准备讲讲 diff
. 它是一个经常被用到却不是很被了解的命令. 我希望 Unix 使用者在读完这篇文章之后能够正确了解这个命令的用途并从中获益. 另外一个有用的命令是: comm
命令. 我们开始吧…
示例文件分别是 first 文件和 second 文件. 如下:
1 | wiw_labs:$ nl first |
diff
命令用来比较这两个文件之间的差异
#diff 命令的用法
我命先从 diff
的用法说起. diff
通常这样使用:
diff first_file second_file
这条命令意即: first_file 和 second_file 有什么不同
#diff 命令如何工作
diff
命令的运作原理就是, 想法设法的让 first 文件和 second 文件一样. 它希望通过更改©, 删除(d) first 文件中的行以使其和 second 文件一模一样. 如果需要, 它还会把 second 文件中的行附加到 first 文件中. 如果你明白我说的什么, 很好, 如果不明白也随便. 当我使用示例给你解释的时候你就会明白的.
diff
就是通过下面的这些步骤来生成这两个文件的差异报告的:
-
它从 first 文件和 second 文件的第 1 行开始. 如果它们不一样,
diff
便顺着 first 文件往下找, 直到找到和 second 文件中相似的条目. -
如果在 first 文件中没有找到和 second 文件第 1 行相同的行, 它就再从 second 文件的第 2 行开始. 它会在 first 文件中开始找. 然后提议做什么(附加, 更改或删除)
#示例
理论讲得够多了. 我们来点实际例子好解释的更通透一点.
我把这两个文件并排来放, 好理解起来更容易一些. 另外行号也一并显示了出来.
1 | wiw_labs:$ paste first second|nl |
现在, 看一下上面 paste
命令带行号的输出. 注意下面几点:
- first 文件的第 2 行(modem) 和 second 文件的第 4 行(modem) 一致. 所以, 如果我们把 first 文件中的第 1 行换成 second 文件中的 1 到 3 行, 这两个文件的第一部分便都一样了. 输出看起来就会是这样的:
1 | wiw_labs:$ paste first second|nl |
- first 文件的第 4 行(phone) 和 second 文件的第 5 行一致. 这意味着如果我们删除 first 文件中的第 3 行(也就是目前的第 4 行), 这两个文件的第二部分便都一样了.
1 | wiw_labs:$ paste first second|nl |
- first 文件的第 5 行(switch)可用 second 文件的第 6 行(server)替换. 至此, 这两个文件完全一样了.
1 | wiw_labs:$ paste first second|nl |
现在, diff
命令的输出更容易理解了:
1c1,3: 更改 first 文件的第一行为 second 文件的 1 到 3 行
3d4: 从 first 文件中删除第 3 行(modem).
5c6: 更改 first 文件中的第 5 行(switch) 为 second 文件中的第 6 行(server)
现在, 反过来再看一下:
1 | wiw_labs:$ paste second first | nl |
- 我们看到 first 文件的第 4 行(modem) 和 second 文件的第 2 行一致. 所以如果我们把 first 文件的 1 到 3 行替换为 second 文件的第 1 行, 我们得到如下输出:
1 | wiw_labs:$ paste second first | nl |
- 现在, second 文件的第 3 行(monitor) 在 first 文件中并不存在. 所以, 把它附加到 first 文件的第 4 行(modem)后面. 要记住
diff
命令的输出中的行号永远指的是原始的行号. 现在, 输出看起来是这样的:
1 | wiw_labs:$ paste second first | nl |
- first 文件的第 6 行(server)需要改成 second 文件的第 5 行(switch). 更改之后, 两个文件便都一样了:
1 | 1 computer computer |
现在, 更容易理解 diff
命令的输出了:
1,3c1: 把 first 文件的第 1 到 3 行改为 second 文件的第 1 行.
4a3: 在 first 文件的第 4 行(modem)后面附加上 second 文件的第 3 行(monitor).
6c5: 把 first 文件的第 6 行(server)改为 second 文件的第 5 行(switch).