patch コマンド

目的

変更内容をファイルに適用します。

構文

patch-b [ -B Prefix ] ] [  -f ] [ -l ] [ -N ] [ -R ] [  -s ] [  -v ] [  -c | -e | -n  | -u ] [  -d Directory ] [  -D Define ] [  -F Number ] [  -i PatchFile ] [  -o OutFile ] [  -p Number ] [  -r RejectFile ] [  -x Number ] [ File ]

説明

patch コマンドは、ファイルの変更方法についてのソース・ファイルの命令を読み、その変更を適用します。 このソース・ファイルには、diff -c または -u コマンドで作成される差分に関するリスト (diff リスト) が入っており、diff コマンド出力の 1 つまたは複数のセットを、通常 hunk (ハンク) と呼びます。

patch コマンドは、パッチ・ファイル内の先行テキストをスキップし、実際の diff リストを適用し、後続のテキストをスキップします。 したがって、diff リストを含むメッセージをパッチ・ファイルとして使用しても、patch コマンドは引き続き機能します。 その場合、diff リスト全体が一定量だけ字下げされていると、patch コマンドもそのスペーシングに合わせて調整します。

元のファイル内の行範囲を変更するには、パッチ内の各ハンクが別個の diff リストでなくてはなりません。 パッチ内の連続するハンクの行番号は、昇順で指定しなくてはなりません。

ファイル名の判別

File パラメーターを指定しないと、patch コマンドは以下の手順を行って、編集するファイルの名前を取得します。

  1. コンテキスト diff リストのヘッダーでは、
    • diff のタイプがコピー・コンテキストである場合、ファイル名は *** (3 個のアスタリスク) または —- (3 個のダッシュ) で始まる行から判別されます。 *** で始まる行はパッチが取り出されたファイルの名前を示し、—- で始まる行はパッチを適用するファイルの名前を示します。 既存のファイルの最も短い名前が選択されます。
    • diff のタイプが統合コンテキストである場合、 ファイル名は --- (3 個のダッシュ) または +++ (3 個のプラス) で始まる行で判別されます。--- で始まる行は、パッチが取り出されたファイルの名前を示し、+++ で始まる行はパッチを適用するファイルの名前を示します。 既存のファイルの最も短い名前が選択されます。
  2. 先行テキスト内に Index: 行があると、patch コマンドはその行のファイル名を使おうとします。
  3. コンテキスト diff ヘッダーは Index: 行よりも優先されます。
  4. 先行テキストからファイル名を判別できない場合、patch コマンドは、 パッチするファイルの名前の入力を求めるプロンプトを表示します。
  5. 元のファイルが見つからなくても、適切な SCCS ファイルまたは RCS ファイルが使用可能であれば、patch コマンドはそのファイルを取得またはチェックアウトしようとします。
  6. 先行テキストに Prereq: 行があると、patch コマンドは前提条件の行から最初のワード (通常はバージョン番号) を取り出し、入力ファイルにそのワードがあるかどうかを調べます。見つからない場合は、patch コマンドは処理を続ける前に確認を求めるプロンプトを表示します。

パッチの適用

パッチ・ファイルに複数のパッチが入っていると、patch コマンドは各 diff リストを別のパッチ・ファイルから取り出したものとして適用しようとします。 この場合、パッチされるファイルの名前は diff リストごとに判別され、各 diff リストの前に表示されるヘッダー・テキスト内でファイル名や改訂レベルなどの情報が検査されます。

-c -e -n、または -u フラグを指定すると、patch コマンドは各ハンク内の情報を、それぞれコピー・コンテキストの差分、ed エディターの差分、通常の差分、または統合コンテキストの差分として、おのおのを解釈します。 これらのフラグを指定しないと、patch コマンドはハンク内の情報のフォーマットに基づいて差分のタイプを判別します。

patch コマンドは、ハンクの最初の行の番号を取り出して、直前のハンクを適用することによって生じる行オフセットを加算または減算することにより、各ハンクの適用個所を検索します。 この行位置で正確に一致させることができなければ、patch コマンドはハンクの内容と正確に一致する行の集合を、順方向と逆方向の両方にスキャンします。

この適用個所が見つからず、patch コマンドがコンテキスト diff リストを適用している場合は、patch コマンドは、完全ではないが部分的に一致するものを検索することができます。 fuzz ファクター は、部分的に一致する行がどのくらいあるかを指定します。 fuzz ファクターを 1 以上の値に設定すると、patch コマンドは 2 回目のスキャンを実行します。このときはコンテキストの先頭行と最終行を無視します。 一致するものがない場合、最大 fuzz ファクターが 2 以上に設定されていると、patch コマンドは 3 回目のスキャンを実行します。このときはコンテキストの最初の 2 行と最後の 2 行を無視します (デフォルトの最大 fuzz ファクターは 2 です)。 これで一致するものがない場合、patch コマンドはそのハンクをリジェクト・ファイルに入れます。 リジェクト・ファイルは、出力ファイルと同じ名前と接尾部 .rej で作成されます。 この命名規則は、-r フラグを指定すると上書きできます。

リジェクトされたハンクは、パッチ・ファイルのフォーマットに関係なく コピー・コンテキスト diff リスト・フォーマットで書かれます。 入力が通常または ed エディター・スタイルの差分であれば、リジェクト・ファイルには コピー・コンテキスト・フォーマットの行がない差分が含まれることがあります。 リジェクト・ファイル内のハンクに関する行番号は、パッチ・ファイル内の行番号とは異なることがあります。 これは、リジェクト・ファイルの行番号には、旧ファイルではなく新規ファイル内で失敗したハンクの位置の近似値が反映されるからです。

各ハンクが完了するたびに、patch コマンドはハンクが正常に終了したか失敗したかを示します。 また、各ハンクに想定された新しい行番号も表示されます。 この行番号が diff リスト内で指定した行番号と異なる場合は、オフセットが通知されます。 また、patch コマンドは、fuzz ファクターを使用して一致を探したかどうかも表示します。

注: 1 つの広範なオフセットが通知されると、ハンクが正しくないロケーションにインストールされた可能性があります。fuzz ファクターを使用した場合も、間違った配置を示すことがあります。

ほかのユーザーのためのパッチの準備

ほかのユーザーに配布するパッチを準備するプログラマーは、ほかにも以下のガイドラインに注意しなくてはなりません。

  • 同じパッチを 2 回適用しようとすると、patch コマンドは 2 回目の適用が逆パッチであると想定し、逆パッチの確認を求めるプロンプトを表示します。したがって、逆パッチを適用するとユーザーは既にパッチを適用したかどうかがわかりにくくなるので、逆パッチを送信しないようにしてください。
  • 最新のパッチ・レベルで更新される patchlevel.h ファイルを保管することをお勧めします。これにより、送信するパッチ・ファイル内の最初の diff リストとして、パッチ・レベルを使用できます。 パッチに Prereq: 行が含まれていると、秩序の正しくないパッチに対しては必ず警告されます。
  • コンテキスト diff リスト・ヘッダーで、 または Index: 行で、ファイル名を正しく指定しなくてはなりません。サブディレクトリー内のものをパッチする場合は、必要に応じて -p フラグを指定するようにパッチ・ユーザーに必ず指示してください。
  • null ファイルを作成したいファイルと比較する diff リストを送信することによって、ファイルを作成することができます。ただしこの方法は、作成したいファイルがターゲット・ディレクトリー内に存在していない場合にしか使用できません。
  • 多数の diff リストを 1 つのファイルに入れることは可能ですが、関連するパッチを別々のファイルにグループ化しておくことをお勧めします。
  • patch コマンドは、ed スクリプト内の行番号が正しくないかどうかを表示できません。 変更または削除コマンドを見つけたときに、通常 diff リスト内の正しくない行番号を示すことだけができます。fuzz ファクター 3 を使用するコンテキスト diff リストには、同じ行番号の問題が発生することがあります。 このような場合には、適切な対話型インターフェースを追加するまでは、コンテキスト diff リストを使用して変更が正確かどうかを検査してください。 エラーが発生せずにコンパイルされた場合は、一般にパッチが機能したことを意味しますが、パッチ機能を絶対保証できるわけではありません。
  • patch コマンドの結果は、パッチが、 その生成元ファイルと正確に同じバージョンに適用されるときだけ保証されます。
  • 以下のようにコードが重複する場合を仮定します。
    #ifdef 
    ... NEWCODE
    #else
    ... OLDCODE
    # endif
    patch コマンドは、両方のバージョンともパッチできません。 patch コマンドが正常に終了した場合は、正しくないバージョンをパッチして、正常な終了状況を戻した可能性があります。

フラグ

項目 説明
-b 差分が適用される前に、修正される各ファイルのコピーを保存します。 コピーされた元のファイルは、同じ名前に接尾部 .orig が付いたファイルになります。 その名前のファイルが既に存在する場合は上書きされます。 複数のパッチを同じファイルに適用すると、最初のパッチの時点で元のファイルのコピーが 1 つだけ作成されます。 -o OutFile フラグも指定すると、.orig ファイルは作成されません。しかし、指定された out ファイルが既に存在する場合は、OutFile.orig が作成されます。
-B Prefix バックアップ・ファイル名の接頭部を指定します。 このフラグは、-b フラグと一緒に指定する場合だけ機能します。
-c パッチ・ファイルをコピー・コンテキスト diff リスト (diff -c または diff -C コマンドの出力) として解釈します。 このフラグは、-e -n、または -u フラグと一緒には指定できません。
-d Directory 処理の前に、現行ディレクトリーを指定したディレクトリーに変更します。
-D Define 以下の C プリプロセッサー命令で変更個所をマークします。
#ifdef Define
...  (NEWCODE)
#else
...  (OLDCODE)
#endif /* Define */

Define 変数は差分指定記号として使用されます。 このフラグは、通常フォーマットまたはコンテキスト・フォーマットの diff リストがパッチ・ファイルとして使用される場合にのみ機能します。

-e パッチ・ファイルを ed エディター・スクリプトとして解釈します。 このフラグは、-c-n、 または -u フラグと一緒には指定できません。
-f ユーザーへの照会を抑制します。 コメント表示を抑制するには、-s フラグを指定します。
-F Number 最大 fuzz ファクターを設定します。 このフラグはコンテキスト diff リストにのみ適用され、patch コマンドは、ハンクのインストール先を判別するときに、指定された行数を無視します。 -F フラグを指定しない場合、デフォルトの fuzz ファクターは 2 です。このファクターは、コンテキスト diff リストの内容の行数 (通常は 3) よりも大きい値には設定できません。

注: 大きい値の fuzz ファクターを使用すると、正確でないパッチの可能性が高くなります。

-i PatchFile パッチ情報を、標準入力からではなく、指定されたファイルから読みます。
-l (小文字の L) diff リスト・スクリプト内のブランク文字のシーケンスを、入力ファイル内のブランク文字のシーケンスと一致させます。 その他の文字は正確に突き合わされます。
-n スクリプトを通常の diff リストとして解釈します。 このフラグは、-c-e、 または -u フラグと一緒には指定できません。
-N 既にファイルに差分が適用されているパッチを無視します。 デフォルトでは、既に差分が適用されているパッチはリジェクトされます。
-o OutFile パッチされるファイルをコピーし、変更を適用し、修正されたバージョンを指定した出力ファイルに書きます。 単一ファイルへの複数のパッチは、以前のパッチで作成されたファイルの中間バージョンに適用されます。 したがって、複数のパッチを適用すると、出力ファイルの複数のバージョンが連結されます。
-p Number パス名ストリップ・カウントを設定します。このカウントは、パッチ・ファイル内で見つかったパス名の処理方法を制御します。 このフラグは、指定したパスとは異なるディレクトリー内にファイルを保持する場合に便利です。 ストリップ・カウントは、パス名の前からストリップされるスラッシュの数を指定します。 中間のディレクトリー名もストリップされます。 例えば、パッチ・ファイルで /u/leon/src/blurf1/blurf1.c を指定したと仮定すると、
  • -p 0 を指定すると、パス名全体が変更されないままになります。
  • -p 1 を指定すると、先行スラッシュが除去され、u/leon/src/blurf1/blurf1.c となります。
  • -p 4 を指定すると、4 つのスラッシュと 3 つのディレクトリーが除去され、blurf1/blurf1.c となります。

-p フラグを指定しないと、ベース名 (パス名の最後のコンポーネント) だけが使用されます。 このフラグは、File パラメーターが指定されない場合にのみ働きます。

-r RejectFile デフォルトのリジェクト・ファイル名を上書きします。 デフォルトのリジェクト・ファイル名は、元のファイル名に接尾部 .rej を付加して作成されます。
-R パッチ・スクリプトの意味を反転させます。 例えば、diff リストを新規バージョンから旧バージョンに対して作成する場合、-R フラグを指定すると、patch コマンドは、スクリプトの各部分を適用する前に反転させます。 リジェクトされた差分は、スワップ後のフォーマットで保存されます。 -R フラグは ed スクリプトと一緒には使用できません。これは、反転操作を再構成するための情報が少な過ぎるからです。 -R フラグを指定しないと、patch コマンドは、パッチ・ファイルの一部が正常に適用されるまで、各部分を通常の意味でも逆の意味でも適用しようとします。 この試みが正常に終了すると、-R フラグを設定するかどうか判断を求めるプロンプトが表示されます。

注: この方法は、最初のコマンドが追加である (つまり、反転で削除になっていた) 通常 diff リストで使用する場合には、反転されたパッチを検出できません。 null のコンテキストはどこにでも一致するので、追加は常に成功します。幸い、ほとんどのパッチでは行を削除するのではなく、行を追加または変更します。 したがって、反転された通常の diff リストは、ほとんど削除で始まるので失敗し、試行錯誤を引き起こします。

-s エラーが発生しない限り、何も表示せずにパッチします。
-u 統一コンテキストの差分としてパッチ・ファイルを解釈します (-u または -U フラグを指定時の diff コマンドの出力)。このフラグは、-c-e、または -n フラグと一緒には指定できません。
-v 改訂ヘッダーとパッチ・レベルを出力します。 -v フラグをほかのフラグと一緒に指定すると、ほかのフラグは無視されます。
-x Number 内部デバッグ・フラグを設定します。 このフラグは patch コマンド開発者専用です。

終了状況

次の終了値が戻されます。

項目 説明
0 正常終了。
1 エラーが発生し、リジェクトされたファイルに 1 つ以上の行が書き込まれました。
>1 エラーが発生しました。

  1. difflisting ファイル内の diff リストをファイル prog.c に適用するには、以下のように入力します。
    patch -i difflisting prog.c
  2. prog.c ファイルの元のバージョンを保存するには、 以下のように入力します。
    patch -b -i difflisting prog.c
    これにより、変更が prog.c に適用され、prog.c の元の内容はファイル prog.c.orig に保存されます。
  3. 元のバージョンを変更せずに prog.c ファイルをパッチするには、以下のように入力します。
    patch -i difflisting -o prog.new prog.c
    これにより、prog.c がソース・ファイルとして使用されますが、変更後のバージョンは prog.new というファイルに書かれます。

ファイル

項目 説明
/usr/bin/patch patch コマンドが入っています。