原文:https://www.shuzhiduo.com/A/1O5ErMybd7/
1.概述
windows系統下面就有不錯的文本對比工具可以使用,例如常用的Beyond Compare,WinMerge都是圖形界面的比較工具而且使用非常方便,如果你僅僅是在windows下工作,這些GUI的比較工具絕對是首選。對於在linux環境下工作的人來說,如果每次想看兩個文件的區別都要將文件下載到windows環境然后用圖形工具進行比較實在是太麻煩了。那么我們必須學會使用linux環境下的比較工具 diff。
diff命令在最簡單的情況下,比較給定的兩個文件的不同。如果使用“-”代替“文件”參數,則要比較的內容將來自標准輸入。diff命令是以逐行的方式,比較文本文件的異同處。如果該命令指定進行目錄的比較,則將會比較該目錄中具有相同文件名的文件,而不會對其子目錄文件進行任何比較操作。
語法
- diff(選項)(參數)
選項
- -<行數>:指定要顯示多少行的文本。此參數必須與-c或-u參數一並使用;
- -a或——text:diff預設只會逐行比較文本文件;
- -b或--ignore-space-change:不檢查空格字符的不同;
- -B或--ignore-blank-lines:不檢查空白行;
- -c:顯示全部內容,並標出不同之處;
- -C<行數>或--context<行數>:與執行“-c-<行數>”指令相同;
- -d或——minimal:使用不同的演算法,以小的單位來做比較;
- -D<巨集名稱>或ifdef<巨集名稱>:此參數的輸出格式可用於前置處理器巨集;
- -e或——ed:此參數的輸出格式可用於ed的script文件;
- -f或-forward-ed:輸出的格式類似ed的script文件,但按照原來文件的順序來顯示不同處;
- -H或--speed-large-files:比較大文件時,可加快速度;
- -l<字符或字符串>或--ignore-matching-lines<字符或字符串>:若兩個文件在某幾行有所不同,而之際航同時都包含了選項中指定的字符或字符串,則不顯示這兩個文件的差異;
- -i或--ignore-case:不檢查大小寫的不同;
- -l或——paginate:將結果交由pr程序來分頁;
- -n或——rcs:將比較結果以RCS的格式來顯示;
- -N或--new-file:在比較目錄時,若文件A僅出現在某個目錄中,預設會顯示:Only in目錄,文件A 若使用-N參數,則diff會將文件A 與一個空白的文件比較;
- -p:若比較的文件為C語言的程序碼文件時,顯示差異所在的函數名稱;
- -P或--unidirectional-new-file:與-N類似,但只有當第二個目錄包含了第一個目錄所沒有的文件時,才會將這個文件與空白的文件做比較;
- -q或--brief:僅顯示有無差異,不顯示詳細的信息;
- -r或——recursive:比較子目錄中的文件;
- -s或--report-identical-files:若沒有發現任何差異,仍然顯示信息;
- -S<文件>或--starting-file<文件>:在比較目錄時,從指定的文件開始比較;
- -t或--expand-tabs:在輸出時,將tab字符展開;
- -T或--initial-tab:在每行前面加上tab字符以便對齊;
- -u,-U<列數>或--unified=<列數>:以合並的方式來顯示文件內容的不同;
- -v或——version:顯示版本信息;
- -w或--ignore-all-space:忽略全部的空格字符;
- -W<寬度>或--width<寬度>:在使用-y參數時,指定欄寬;
- -x<文件名或目錄>或--exclude<文件名或目錄>:不比較選項中所指定的文件或目錄;
- -X<文件>或--exclude-from<文件>;您可以將文件或目錄類型存成文本文件,然后在=<文件>中指定此文本文件;
- -y或--side-by-side:以並列的方式顯示文件的異同之處;
- --help:顯示幫助;
- --left-column:在使用-y參數時,若兩個文件某一行內容相同,則僅在左側的欄位顯示該行內容;
- --suppress-common-lines:在使用-y參數時,僅顯示不同之處。
還有個colordiff命令,用顏色標識不同的地方。需要先安裝
2.diff如何工作,如何理解diff的執行結果
diff分析兩個文件,並輸出兩個文件的不同的行。diff的輸出結果表明需要對一個文件做怎樣的操作之后才能與第二個文件相匹配【或者這么理解:與第一個文件相比,第二個文件發生了那些變化】【git diff的結果輸出也是如此】。diff並不會改變文件的內容,但是diff可以輸出一個ed腳本來應用這些改變。
現在讓我們來看一下diff是如何工作的,假設有兩個文件:
//file1.txt
I need to buy apples.
I need to run the laundry.
I need to wash the dog.
I need to get the car detailed.
//file2.txt
I need to buy apples.
I need to do the laundry.
I need to wash the car.
I need to get the dog detailed.
我們使用diff比較他們的不同:
diff file1.txt file2.txt
輸出如下結果:
2,4c2,4
< I need to run the laundry.
< I need to wash the dog.
< I need to get the car detailed.
---
> I need to do the laundry.
> I need to wash the car.
> I need to get the dog detailed.
我們來說明一下該輸出結果的含義,要明白diff比較結果的含義,我們必須牢記一點,diff描述兩個文件不同的方式是告訴我們怎么樣改變第一個文件之后與第二個文件匹配。我們看看上面的比較結果中的第一行
2,4c2,4
前面的數字2,4表示第一個文件中的行,中間有一個字母c表示需要在第一個文件上做的操作(a=add,c=change,d=delete),后面的數字2,4表示第二個文件中的行。
2,4c2,4 的含義是:第一個文件中的第[2,4]行(注意這是一個閉合區間,包括第2行和第4行)需要做出修改才能與第二個文件中的[2,4]行相匹配。
接下來的內容則告訴我們需要修改的地方,前面帶 < 的部分表示左邊文件的第[2,4]行的內容,而帶> 的部分表示右邊文件的第[2,4]行的內容,中間的 --- 則是兩個文件內容的分隔符號。
3.Normal模式
上面的部分我們說明了如何查看diff命令的結果,實際上對於上面的比較,我們使用的是diff命令的Normal模式,這也是diff命令的默認模式,也就是說diff兩個文件的時候如果不加模式參數則是默認模式進行比較,其效果與(--normal)一樣,我們舉一些例子來說明Normal模式下的輸出結果(前面已經說明了一種比較結果),為了直觀查看兩個文件的不同我在windows下面通過BeyondCompare工具列出兩個文件的不同,而截圖下面的黑色部分則是diff的比較輸出截圖。
第一個文件比第二個文件少了行的情況:
第一個文件比第二個文件多出行的情況:
第一個文件與第二個文件不相同的情況:
以上diff命令執行的時候沒有指定額外的模式參數,所以其使用的是默認的Normal模式,效果與添加命令行參數--normal 是一樣的。
4.Context模式
默認情況下的模式輸出結果實際上是符合計算機的思維方式,不太直觀,所以其輸出結果並不能夠很好的被人理解,diff命令除了默認模式之外還提供了另外兩種模式,Context和Unified模式,本節我們說說如何查閱Context模式下的輸出結果。diff命令應用Context模式只需要添加命令行參數
diff -c 即可,我們先看看兩個案例文件:
接下來說明這兩個文件以diff -c 方式比較的結果:
5.Unified模式
diff還有一種比較方式,也即Unified模式,使用命令行 –u 來執行該模式的比較。其比較結果與Context模式很像,但是簡化了一些輸出,我們看看我們的案例文件,與上面的一樣:
使用diff –u 比較的結果:
可以看到其比較結果與Context模式實際上差不多,只不過將比較結果合並到一起了。
6.比較目錄
使用diff可以比較兩個目錄,其比較格式是 diff directory1 directory2 查看如下目錄比較結果:
比較兩個目錄的時候無非是有的文件僅僅存在於某個目錄中而在另一個目錄中沒有,如果存在同名的文件,則比較這兩個文件的不同。diff比較目錄的結果我們可以結合grep命令篩選出我們想要的輸出,例如僅僅輸出兩個目錄下不同的文件而忽略掉某一個目錄獨有另一個目錄不存在的輸出記錄。
7.參數 -e 將比較的結果保存成一個ed腳本,之后ed程序可以執行該腳本文件,從而將file1修改成與file2的內容相同,這一般在patch的時候有用。
diff -e 1.txt 2.txt > script.txt
這樣就是生成了一個ed可以執行的腳本文件script.txt,生成腳本文件之后我們還需要做一個操作, 在腳本文件末尾添加ed的write指令,只需要執行 echo "w" >>script.txt 將w指令附加到腳本文件的最后一行即可。
那么如何應用該腳本文件呢,可以這樣使用:
ed - 1.txt < script.txt
注意中間的 – 符號表示從標准輸入中讀取,而 < script.txt 則重定向script.txt的內容到標准輸入。這樣執行之后1.txt的內容將與2.txt完全相同。