Skip to content

文件对比

参考《鸟哥的linux私房菜》。

1. diff

diff [OPTION]... FILES
Compare FILES line by line.
FILES are 'FILE1 FILE2' or 'DIR1 DIR2' or 'DIR FILE...' or 'FILE... DIR'.

OPTION
    -s, --report-identical-files  report when two files are the same
    -i, --ignore-case               ignore case differences in file contents
    -B, --ignore-blank-lines        ignore changes where lines are all blank
    -c, -C NUM, --context[=NUM]   对所有文件在不同处都输出一致的 NUM (default 3) 行
    -u, -U NUM, --unified[=NUM]   在不同处的上下文输出一致的 NUM (default 3) 行
    -N, --new-file                  treat absent files as empty
    -a, --text                      treat all files as text
    --binary                        Read and write data in binary mode.
    -r, --recursive                 recursively compare any subdirectories found
[sink@dev vitest]$ diff man_db.conf.bak man.test.conf
# 25表示第一个文件的行号,c表示左边第25行被右边25行取代了,第二个25表示第二个文件的行号
# d表示删除
25c25
< tree holds man pages for what binary directory.
---
> # ie. what man tree holds man pages for what binary directory.

# 输出两行上下文
[sink@dev vitest]$ diff -C 2 man_db.conf.bak man.test.conf
*** man_db.conf.bak     2019-10-10 14:45:12.640893299 +0800
--- man.test.conf       2019-10-08 09:51:29.652930093 +0800
***************
*** 23,27 ****
  #---------------------------------------------------------
  # set up PATH to MANPATH mapping
! tree holds man pages for what binary directory.
  #
  #             *PATH*        ->        *MANPATH*
--- 23,27 ----
  #---------------------------------------------------------
  # set up PATH to MANPATH mapping
! # ie. what man tree holds man pages for what binary directory.
  #
  #             *PATH*        ->        *MANPATH*

# 类似git的形式输出
[sink@dev vitest]$ diff -u man_db.conf.bak man.test.conf
--- man_db.conf.bak     2019-10-10 14:45:12.640893299 +0800
+++ man.test.conf       2019-10-08 09:51:29.652930093 +0800
@@ -22,7 +22,7 @@
 MANDATORY_MANPATH                      /usr/local/share/man
 #---------------------------------------------------------
 # set up PATH to MANPATH mapping
-tree holds man pages for what binary directory.
+# ie. what man tree holds man pages for what binary directory.
 #
 #              *PATH*        ->        *MANPATH*
 #

# 比较文件夹
[sink@dev vitest]$ diff /etc/rc0.d/ /etc/rc5.d/
Only in /etc/rc0.d/: K43vmware-tools-thinprint
Only in /etc/rc0.d/: K90network
Only in /etc/rc0.d/: K99vmware-tools
Only in /etc/rc5.d/: S03vmware-tools
Only in /etc/rc5.d/: S10network
Only in /etc/rc5.d/: S57vmware-tools-thinprint

2. cmp

cmp [OPTION]... FILE1 [FILE2 [SKIP1 [SKIP2]]]
Compare two files byte by byte.
The optional SKIP1 and SKIP2 specify the number of bytes to skip
at the beginning of each file (zero by default).

-b, --print-bytes          print differing bytes
-l, --verbose              output byte numbers and differing byte values。会输出所有的不同,默认只会输出第一处不同。
-n, --bytes=LIMIT          compare at most LIMIT bytes
-s, --quiet, --silent      suppress all normal output
# 某个文件全部读取完毕就不会再继续比较了
[sink@dev vitest]$ cmp -b -l .gitignore-Windows .gitignore-linux
12  15 ^M    12 ^J
13  12 ^J   165 u
14 165 u    143 c
15 143 c    150 h
16 150 h    153 k
17 153 k    166 v
18 166 v    153 k
19 153 k     56 .
20  56 .    160 p
21 160 p    151 i
22 151 i    146 f
23 146 f     12 ^J
cmp: EOF on .gitignore-linux

3. patch

patch [OPTION]... [ORIGFILE [PATCHFILE]]

Input options:
  -p NUM  --strip=NUM  Strip NUM leading components from file names.从补丁文件中删除 NUM 级目录(根据制作补丁文件时的目录决定)
  -R  --reverse  Assume patches were created with old and new files swapped.还原

更新:patch -p NUM < patch_file
还原:patch -R -p NUM < patch_file
[sink@dev vitest]$ cat old; echo '-----'; cat new
I'm old file.
-----
I'm new file.
# 制作补丁文件
[sink@dev vitest]$ diff -uar old new > test.patch
# 更新旧文件
[sink@dev vitest]$ patch -p0 < test.patch
patching file old
[sink@dev vitest]$ cat old; echo '-----'; cat new
I'm new file.
-----
I'm new file.
# 恢复旧文件
[sink@dev vitest]$ patch -R -p0 < test.patch
patching file old
[sink@dev vitest]$ cat old; echo '-----'; cat new
I'm old file.
-----
I'm new file.