diff 指令:檔案比較、diff -u 修補檔格式與選項整理

測試環境RHEL 系列AlmaLinux 9.8root 帳號
文字檢視 · 編輯指令diff位置/usr/bin/diff

diff 指令是逐行比較兩個檔案、只輸出不同行的 Linux 指令。用 diff 比較模擬網頁伺服器設定的舊檔案與新檔案後,三處變更以 2,3c2,3、5d4、6a6 三行呈現,而用 -u 選項儲存的修補檔則以減號與加號整理出相同的變更。

以下輸出中的檔案名稱與內容,以及工作資料夾 /root/work 都是範例值。比較用的檔案全都是為了測試而建立的小檔案。

1️⃣ diff 指令的基本用法與輸出讀法

指令的基本形式依序是 diff、選項、第一個檔案、第二個檔案。它會連同行號輸出,要讓第一個檔案與第二個檔案相同,必須修改、刪除、新增哪些行。

用來比較的兩個檔案,是模擬網頁伺服器設定的六行檔案。

cd /root/work
cat config-old.conf
# app config
listen 80
server_name example.com
root /var/www/html
gzip off
log_level warn
cat config-new.conf
# app config
listen 443
server_name example.com www.example.com
root /var/www/html
log_level warn
cache on

不加選項比較了這兩個檔案。

diff config-old.conf config-new.conf
2,3c2,3
< listen 80
< server_name example.com
---
> listen 443
> server_name example.com www.example.com
5d4
< gzip off
6a6
> cache on
echo $?
1

輸出中位置行與內容行交替出現。位置行中間的字母 c 是修改、d 是刪除、a 是新增,字母左邊是第一個檔案的行號,右邊是第二個檔案的行號。有不同之處時,結束代碼是 1。

輸出說明
2,3c2,3把第一個檔案的第 2~3 行改成第二個檔案的第 2~3 行(change)
5d4刪除第一個檔案的第 5 行(delete)。刪除後會對上第二個檔案第 4 行之後
6a6在第一個檔案的第 6 行之後加上第二個檔案的第 6 行(add)
< 行第一個檔案中的行
> 行第二個檔案中的行
---修改的行(c)中,第一個檔案一側與第二個檔案一側的分界

比較內容相同的檔案時,不會輸出任何內容,並以結束代碼 0 結束。

diff config-old.conf config-copy.conf
echo $?
0

指定不存在的檔案時,會出現錯誤訊息,結束代碼是 2。

diff config-old.conf nosuch.conf
diff: nosuch.conf: No such file or directory
echo $?
2

在指令稿中,可以用這三個值區分相同、不同與錯誤。

2️⃣ diff -u 統一格式與修補檔

預設輸出只有變更的行,因此在有數百行的設定檔中,很難看出那些行在哪個設定附近。加上 -u 後,會以統一格式(unified)輸出,把變更行前後各最多三行一併納入。

diff -u config-old.conf config-new.conf
--- config-old.conf     2026-10-29 02:24:50.840228932 +0000
+++ config-new.conf     2026-10-29 02:24:50.840228932 +0000
@@ -1,6 +1,6 @@
 # app config
-listen 80
-server_name example.com
+listen 443
+server_name example.com www.example.com
 root /var/www/html
-gzip off
 log_level warn
+cache on

開頭兩行(---、+++)顯示兩個檔案的名稱與修改時間,@@ -1,6 +1,6 @@ 這一行則是把第一個檔案從第 1 行起的 6 行與第二個檔案從第 1 行起的 6 行合在一起的區塊(hunk)。其下的各行,開頭是 - 表示從第一個檔案刪除的行,開頭是 + 表示加到第二個檔案的行,開頭是空白則表示兩個檔案中相同的行。

-c 是上下文格式(context)。它會分別輸出第一個檔案的區塊與第二個檔案的區塊,變更的行前面有驚嘆號,刪除的行有減號,新增的行有加號。

diff -c config-old.conf config-new.conf
*** config-old.conf     Thu Oct 29 02:24:50 2026
--- config-new.conf     Thu Oct 29 02:24:50 2026
***************
*** 1,6 ****
  # app config
! listen 80
! server_name example.com
  root /var/www/html
- gzip off
  log_level warn
--- 1,6 ----
  # app config
! listen 443
! server_name example.com www.example.com
  root /var/www/html
  log_level warn
+ cache on

同樣的變更,-c 因為未變更的行在兩個區塊各出現一次,所以比 -u 長。

把 -u 的輸出存成檔案,那個檔案就是修補檔。即使把輸出送到檔案,diff 的結束代碼仍然是 1。

diff -u config-old.conf config-new.conf > /root/work/config.patch
echo $?
1
cat /root/work/config.patch
--- config-old.conf     2026-10-29 02:24:50.840228932 +0000
+++ config-new.conf     2026-10-29 02:24:50.840228932 +0000
@@ -1,6 +1,6 @@
 # app config
-listen 80
-server_name example.com
+listen 443
+server_name example.com www.example.com
 root /var/www/html
-gzip off
 log_level warn
+cache on

儲存的檔案內容與畫面上輸出的 -u 結果相同。把這個檔案交給 patch 指令,就能把第一個檔案改成與第二個檔案相同的內容。

3️⃣ diff 選項整理與忽略空白、大小寫

用手抄寫設定時,會出現內容相同、只有大小寫或空白不同的行。第二組範例檔案把第一行的大寫 L 改成小寫,把第二行的一個空白改成兩個,並加了一個空行。

cat case-a.txt
Listen 80
ServerName example.com
DocumentRoot /var/www/html
cat case-b.txt
listen 80
ServerName  example.com

DocumentRoot /var/www/html
diff case-a.txt case-b.txt
1,2c1,3
< Listen 80
< ServerName example.com
---
> listen 80
> ServerName  example.com
>

不加選項比較時,意思相同的第 1~2 行也會顯示為變更的行。用 -i 忽略大小寫後,Listen 這一行消失,只剩第一個檔案的第 2 行。

diff -i case-a.txt case-b.txt
2c2,3
< ServerName example.com
---
> ServerName  example.com
>

再加上 -w 會忽略行內所有空白,ServerName 這一行也變成相同的行,只剩在第 3 行加上的一個空行。把 -w 換成只忽略空白數量的 -b,在這組檔案中也得到相同的結果。

diff -i -w case-a.txt case-b.txt
2a3
>

連 -B 也加上後,空行的差異也會被忽略,因此沒有輸出,並以結束代碼 0 結束。

diff -i -w -B case-a.txt case-b.txt
echo $?
0

要把兩個檔案左右並排檢視時,使用 -y。預設寬度是 130 欄,因此用 -W 70 縮小。

diff -y -W 70 config-old.conf config-new.conf
# app config                            # app config
listen 80                         |     listen 443
server_name example.com           |     server_name example.com www.ex
root /var/www/html                      root /var/www/html
gzip off                          <
log_level warn                          log_level warn
                                  >     cache on

中間的直線(|)表示變更的行,< 表示只在第一個檔案中的行,> 表示只在第二個檔案中的行。寬度縮小後,較長的行會被截斷。server_name 這一行在右側只顯示到 www.ex。

加上 --suppress-common-lines 後,會去掉相同的行,只留下不同的行。

diff -y --suppress-common-lines -W 70 config-old.conf config-new.conf
listen 80                         |     listen 443
server_name example.com           |     server_name example.com www.ex
gzip off                          <
                                  >     cache on

只想確認相同或不同、而不看差異內容時,使用 -q。檔案相同時 -q 不會輸出任何內容,因此要得到一行說明兩者相同的訊息,就使用 -s。

diff -q config-old.conf config-new.conf
Files config-old.conf and config-new.conf differ
diff -s config-old.conf config-copy.conf
Files config-old.conf and config-copy.conf are identical

選項整理在下方兩個分頁。

選項複製說明
-u, --unified以統一格式輸出,把變更行前後各最多三行一併納入
-c, --context分別輸出第一個檔案區塊與第二個檔案區塊的上下文格式
-i, --ignore-case忽略大小寫的差異
-w, --ignore-all-space忽略行內所有空白
-b, --ignore-space-change只忽略空白數量的差異
-B, --ignore-blank-lines忽略空行的差異
-y, --side-by-side把兩個檔案左右並排輸出
-W, --widthNUM指定並排輸出時的寬度。預設值是 130 欄
--suppress-common-lines並排輸出時去掉相同的行,只輸出不同的行
-q, --brief只輸出相同或不同。相同時不輸出任何內容
-s, --report-identical-files兩個檔案相同時,輸出一行說明兩者相同的訊息
-r, --recursive連子資料夾內的檔案也一併比較
選項複製說明
-U, --unifiedNUM指定統一格式中一併輸出的前後行數。預設值是 3
-N, --new-file把其中一側沒有的檔案視為空檔案
-x, --excludePAT把名稱符合樣式的檔案排除在比較之外
-I, --ignore-matching-linesRE變更的行全都符合正規表示式時,忽略該差異
-Z, --ignore-trailing-space忽略行尾的空白
-E, --ignore-tab-expansion忽略把定位字元換成空白所產生的差異
-a, --text把所有檔案視為文字
--strip-trailing-cr去掉行尾的歸位字元後再比較
--colorWHEN為輸出加上顏色。WHEN 是 never、always、auto
-v, --version輸出版本資訊

🔲 diff 指令模擬器

在下方的模擬器中,可以用本文的範例檔案直接輸入 diff。可以用 -u 儲存修補檔,或用 -i -w -B、-rq 比較,在 config-new.conf 加一行後再比較一次,就會出現變更後的結果。

diff 指令模擬器diff · root 帳號
[root@server work]#
用鍵盤 ↑↓ 鍵可叫出先前輸入過的指令。

4️⃣ 用 diff -r 比較資料夾

像部署網站檔案的前後那樣要一次比較多個檔案時,就寫資料夾名稱而不是檔案。範例資料夾 site-v1 與 site-v2 都有 index.html 與 css 資料夾,about.html 與 contact.html 則各只在其中一側。

diff site-v1 site-v2
Only in site-v1: about.html
Only in site-v2: contact.html
Common subdirectories: site-v1/css and site-v2/css
diff site-v1/index.html site-v2/index.html
2,3c2,3
< <p>Version 1</p>
< <a href="about.html">About</a>
---
> <p>Version 2</p>
> <a href="contact.html">Contact</a>

不加選項比較資料夾時,只在其中一側的檔案以 [Only in] 行顯示,子資料夾只以 [Common subdirectories] 行顯示,不會比較子資料夾內的檔案。兩個資料夾中同名的 index.html,會在 [diff site-v1/index.html site-v2/index.html] 行之下輸出差異。加上 -r 後,連 css 資料夾內 style.css 中變更的顏色值也會輸出。

diff -r site-v1 site-v2
Only in site-v1: about.html
Only in site-v2: contact.html
diff -r site-v1/css/style.css site-v2/css/style.css
2c2
< h1 { color: #222; }
---
> h1 { color: #0a58ca; }
diff -r site-v1/index.html site-v2/index.html
2,3c2,3
< <p>Version 1</p>
< <a href="about.html">About</a>
---
> <p>Version 2</p>
> <a href="contact.html">Contact</a>

檔案很多的資料夾,先用 -rq 確認變更的檔案清單,再用 diff 只比較需要的檔案。

diff -rq site-v1 site-v2
Only in site-v1: about.html
Only in site-v2: contact.html
Files site-v1/css/style.css and site-v2/css/style.css differ
Files site-v1/index.html and site-v2/index.html differ

🔢 FAQ & 推薦內容

cmp 以位元組為單位比較兩個檔案,只輸出第一個不同的位置。用 cmp 比較本文的兩個設定檔,結果是 [config-old.conf config-new.conf differ: char 21, line 2] 這一行。它用來確認逐行比較沒有意義的壓縮檔或圖片是否相同。

把原始檔案與修補檔依序交給 patch 指令([patch config-old.conf config.patch])。patch 會直接修改原始檔案,因此要用 -o 把結果寫到另一個檔案,或先套用在副本上。

用 --color[=WHEN] 選項可以加上顏色,WHEN 的位置填入 never、always、auto。省略值的 --color 與 auto 相同,只有輸出到終端機時才加上顏色,因此交給 less 之類的其他指令時也要保留顏色的話,就使用 --color=always。

ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Prove your humanity: 9   +   5   =