命令套用
用途
對檔案套用更改。
語法
patch [ -b [ -B Prefix ] ] [ -f ] [ -l ] [ -N ] [ -R ] [ -s ] [ -v ] [ -c | -e | -n ] [ -d Directory ] [ -D Define ] [ -F Number ] [ -i PatchFile ] [ -o OutFile ] [ -p Number ] [ -r RejectFile ] [ -x Number ] [ File ]
描述
patch 命令讀取如何更改檔案的源檔案指示信息,然後套用這些更改。源檔案包含由 diff 命令產生的差別列表(或者 diff 列表)。差異列表是比較兩個檔案和構建關於如何糾正差別的指示信息的結果。預設情況下,patch 命令使用從標準輸入讀入的源檔案,但是使用 -i 標誌和 PatchFile 變數可以覆蓋此設定。
差異列表有三種格式:正常、上下文或者是 ed 編輯器風格。patch 命令確定差異列表格式,除非被 -c、-e 或 -n 標誌否決。
預設情況下,檔案的打過補丁的版本替換原始版本。指定 -b 標誌時,每個補丁檔案的原檔案保存在同名的檔案中,只是在檔案名稱後附加了後綴 .orig。使用 -o 標誌也可以指定輸出的目的地。
-p 標誌使得無需手工編輯補丁檔案就可以定製補丁檔案到本地用戶目錄結構中。通過指定從路徑全稱除去多少部分可以做到這一點。例如,如果補丁檔案包含路徑名稱 /curds/whey/src/blurfl/blurfl.c,那么:
* -p 0 導致使用完整路徑名。
* -p 1 除去前導斜槓,留下 curds/whey/src/blurfl/blurfl.c。
* -p 4 除去前導斜槓和前三個目錄,留下 blurfl/blurfl.c。
不指定 -p 標誌使得 patch 命令使用基本名稱。在上面的示例中,此檔案為 blurfl.c。
補丁檔案格式
補丁檔案必須包含單行或多行頭信息,後跟單個或多個補丁。每個補丁必須包含一行或多行檔案名稱標識,其格式由 diff -c 命令和單個或多個 diff 命令輸出集產生,通常稱為 hunks。
patch 命令跳過補丁檔案中的任何前導文本,然後套用實際的差異列表,並且跳過任何後續文本。因而,可以將包含差異列表的檔案或訊息當成補丁檔案使用,此時 patch 命令仍然有效。在這種情況下,如果整個差異列表使用一致的數量縮進,patch 命令也會調整其間距。
要更改原始檔案中的行範圍,每一補丁中的塊(hunk)必須為單獨的差異列表。補丁內連續塊(hunk)的行號必須以升序方式出現。
檔案名稱
如果沒有指定 File 參數,要獲得供編輯的檔案名稱,patch 命令會執行下面的步驟:
1. 在上下文差異列表的頭部分,檔案名稱由以 ***(三個星號)或者 ---(三個破折號)開頭的行確定。以 *** 開頭的行表示獲取補丁的檔案,然而以 --- 開頭的行表示應該套用補丁的檔案名稱。選擇存在檔案的最短名稱。
2. 如果在前導文本中有 Index: 行,patch 命令嘗試使用來自於那一行中的檔案名稱。
3. 上下文差異檔案頭優先於 Index: 行。
4. 如果從前導文本中不能確定檔案名稱,patch 命令提示輸入需要打補丁的檔案名稱。
5. 如果不能找到原始檔案,但是有適合的 SCCS 或 RCS 檔案可用,patch 命令嘗試獲取或檢出檔案。
6. 如果前導文本包含 Prereq: 行,patch 命令從先決條件行中獲取第一個詞(通常是版本號)並且檢查輸入檔案看是否能找到那個詞。如果找不到,patch 命令在繼續運行前會提示確認。
應用程式
如果補丁檔案包含不止一個補丁,patch 命令嘗試套用每個差異列表,就好像它來自於單獨的補丁檔案。在這種情況下,為每個差異列表確定需要打補丁的檔案名稱,並且審查每個差異列表前的頭文本以獲得如檔案名稱和修訂版級別的信息。
如果指定 -c、 -e 或 -n 標誌,patch 命令將每塊(hunk)內的信息分別解釋成上下文差別、ed 編輯器差別或者正常差別。否則,patch 命令確定基於塊(hunk)內信息格式的差別類型。
patch 命令通過獲取塊(hunk)的首行序號和添加或減去由於套用前一塊(hunk)而產生的任何行偏移來搜尋位置以套用每一塊(hunk)。如果在這一行位置不可能有精確匹配,patch 命令前後搜尋以獲取與塊(hunk)的內容精確匹配的行集合。
如果找不到這些位置,且如果 patch 命令正在套用上下文差異列表,patch 命令能進行非精確搜尋。fuzz factor 指定了非精確匹配的行數目。如果模糊因子設定成 1 或者更大,patch 命令執行第二次掃描,這一次忽略上下文的第一行和最後一行。如果沒有匹配結果,且最大模糊因子設定成 2 或者更大, patch 命令執行第三次掃描,這一次會忽略上下文的前兩行和最後兩行。(預設模糊因子最大值為 2)。如果找不到匹配的位置,patch 命令在拒絕檔案中放置塊(hunk)。創建拒絕檔案時,其名稱和輸出檔案一樣,只是在檔案名稱有後綴 .rej。使用 -r 標誌可以覆蓋此命名約定。
以上下文差異列表格式寫拒絕塊(hunk),而不管補丁檔案的格式如何。如果輸入是正常差別或 ed 編輯器樣式差別,拒絕檔案可能包含上下文格式零行差別。拒絕檔案中塊(hunk)的行編號可能與補丁檔案中的行編號不同。這是因為拒絕檔案的行編號反映了新檔案而不是老檔案中故障塊(hunk)的大約位置。
當完成每塊(hunk)後,patch 命令會告訴您該塊(hunk)是成功還是失敗。也可以獲知為每塊(hunk)假定的新行編號。如果這與差異列表中指定的行編號不同,就會報告偏移量。patch 命令也說明是否使用模糊因子來進行匹配。
註:單一的大偏移可能表示塊(hunk)安裝位置不正確。模糊因子的使用可能表示布局不正確。
準備補丁
原則
準備將補丁裝載給其它用戶的程式設計師應該考慮下面的附加原則:
* 如果想兩次套用同一補丁,patch 命令假定第二個應用程式應該是逆向補丁,並且提示確認此逆向。因此,避免傳送出這些逆向補丁,因為它使用戶疑惑他們是否已經套用了此補丁。
* 建議保留使用最新補丁級別更新的 patchlevel.h 檔案。補丁級別可以用作所傳送的補丁檔案中的第一個差異列表。如果補丁中包含 Prereq: 行,用戶不能套用順序混亂的補丁,同時不收到警告。
* 在上下文差異列表的頭中或者使用 Index: 行以確保正確指定了檔案名稱。如果正在子目錄中打某些補丁,請確保通知補丁用戶在需要時指定 -p 標誌。
* 可以通過傳送差異列表創建檔案,此列表比較一個空檔案和想要創建的檔案。然而,這個方法只有在想要創建的檔案的確不存在於目標目錄時才有效。
* 雖然可以將許多差分列表放置到一個檔案中,但是將相關補丁分組到單獨的檔案中會更好。
* patch 命令不能說明 ed 腳本中的行編號是否正確,只能在當它找到更改或刪除命令時才能檢測正常差異列表中不正確的行編號。使用模糊因子為 3 的上下文差異列表可能有同樣的行編號問題。除非添加了一個適當的互動式接口,在這種情形下才使用上下文差異列表來檢測更改的正確性。編譯無誤通常表示補丁工作正常,但是它並不表示沒有錯誤。
* 只有當補丁套用到與生成補丁的完全同一版本的檔案中,才保證 patch 命令的結果。
* 如果代碼重複,例如:
#ifdef
... NEWCODE
#else
... OLDCODE
# endif
patch 命令不能為兩個版本都打補丁。如果 patch 命令成功,它可能補丁了錯誤版本但是返回了一個成功的退出狀態。
標誌
-b 在套用差別前保存每個修改後檔案的副本。複製的原始檔案歸檔時與原檔案同名且添加了後綴 .orig。如果使用那個名稱的檔案已經存在,它就被覆蓋。如果對同一檔案套用多個補丁,原始檔案只生成一個副本(在第一次補丁時)。如果也指定 -o OutFile 標誌,就不會創建 .orig 檔案。但是如果指定檔案已經存在,就創建 OutFile.orig。
-B Prefix 指定備份檔案名稱稱的前綴。此標誌只有在和 -b 標誌連線使用時才有效。
-c 將補丁檔案解釋成上下文差異列表(diff -c 或 diff -C 命令的輸出)。此標誌不能和 -e 或 -n 標誌一起使用。
-d Directory 在處理前,更改當前目錄到指定目錄。
-D Define 使用下面的 C 預處理器構造標記更改:
#ifdef Define
... (NEWCODE)
#else
... (OLDCODE)
#endif /* Define */
Define 變數用作差分符號。此標誌只有當正常或上下文格式差異列表用作補丁檔案時才有效。
-e 將補丁檔案解釋成 ed 編輯器腳本。此標誌不能和 -c 或 -n 標誌一起使用。
-f 禁止查詢用戶。要禁止注釋,使用 -s 標誌。
-F Number 設定最大模糊因子。此標誌只套用於上下文差異列表,它使 patch 命令在確定塊(hunk)的安裝位置時忽略指定行編號。如果沒有指定 -F 標誌,預設模糊因子為 2。此因子不可以設定成大於上下文差異列表中內容的行的數目(通常為 3)。
註:較大的模糊因子會增加錯誤補丁的可能性。
-i PatchFile 從指定檔案,而不是從標準輸入中讀取補丁信息。
-l (L 的小寫)使差異列表腳本中的任何空格字元序列匹配輸入檔案中的任何空格字元序列。精確匹配其它字元。
-n 將腳本解釋成正常差異列表。此標誌不能和 -c 或 -e 標誌一起使用。
-N 忽略差別已經向檔案套用了的補丁。預設情況下,會拒絕已經套用的補丁。
-o OutFile 複製要打補丁的檔案,然後套用更改,接著將修改版本寫到指定的輸出檔案。單個檔案的多個補丁套用於以前補丁所創建的檔案的中間版本。因此,多補丁會生成輸出檔案的多個連線版本。
-p Number 設定路徑名的剝離數目,它控制如何處理在補丁檔案中找到的路徑名稱。如果將檔案保留在與指定路徑不同的目錄中,此標誌就有用。剝離數目指定了從路徑名前去除多少個斜槓。也去除所有中間的目錄名。例如,假定補丁檔案指定 /u/leon/src/blurf1/blurf1.c:
* -p 0 留下未修改的完整路徑名。
* -p 1 除去前導斜槓,留下 u/leon/src/blurf1/blurf1.c。
* -p 4 卸下四個斜槓和三個目錄,留下 blurf1/blurf1.c。
如果沒有指定 -p 標誌,只使用基本名稱(最後的路徑名稱組件)。此標誌只有在沒有指定 File 參數時才起作用。
-r RejectFile 覆蓋預設拒絕檔案名稱。通過附加後綴 .rej 到原始檔案名稱中,就形成了預設拒絕檔案名稱。
-R 逆向補丁腳本理解。例如,如果從新版本到舊版本創建差異列表,使用 -R 標誌使 patch 命令在套用前逆向腳本的每個部分。以交換格式保存拒絕差別。 -R 標誌不能和 ed 腳本一起使用,因為其中只有很少的信息可以重新構造逆向操作。如果沒有指定 -R 標誌,patch 命令嘗試以逆向理解和正常理解套用每個部分,直到成功套用補丁檔案的每一部分。如果嘗試成功,提示用戶確定是否應該設定 -R 標誌。
註:如果此方法和第一個命令是附加命令(就是說,逆序是刪除)的正常差異列表一起使用,它就不能檢測逆向補丁。因為空上下文無論在何處都匹配,所以附加總是成功的。幸運的是,大多數補丁是添加或更改行而不是刪除行。因此大多數逆序的正常差異列表以一個刪除開始,它導致故障,並且引起啟發(heuristic)。
-s 靜默地進行補丁,直到發生錯誤。
-v 列印修訂版頭和補丁級別。如果 -v 標誌和其它標誌一起使用,就忽略其它標誌。
-x Number 設定內部調試標誌。此標誌只適用於 patch 命令開發者。
退出狀態
返回下面的出口值:
0 成功完成。
1 產生錯誤。
示例
1. 要將 difflisting 檔案中的差異列表套用到 prog.c 檔案,請輸入:
patch -i difflisting prog.c
2. 要保存 prog.c 檔案的原始版本,請輸入:
patch -b -i difflisting prog.c
它將更改套用到 prog.c 並且在 prog.c.orig 檔案中保存 prog.c 的原始內容。
3. 要打補丁到 prog.c 檔案而不改變原始版本,請輸入:
patch -i difflisting -o prog.new prog.c
它將 prog.c 當成源檔案使用,但是更改後的版本寫到名為 prog.new 的檔案中。
檔案
/usr/bin/patch 包含 patch 命令。