名前

patch — オリジナルファイルに差分ファイルを適用する

書式

patch [options] [originalfile [patchfile]]

通常は、次の簡単な形式で使用します。

patch -pnum <patchfile

説明

patchは、diffプログラムが生成した差分リストを含むパッチファイルpatchfileを受け取り、その差分を1個または複数の元のファイルに適用して、変更後のファイルを生成します。通常、変更後のファイルは元のファイルと置き換わります。バックアップも作成できます。-bまたは--backupオプションを参照してください。変更するファイルの名前は通常パッチファイルから取得しますが、変更するファイルが1個だけなら、コマンドラインでoriginalfileとして指定できます。

起動すると、patchは差分リストの形式を判別しようとします。ただし、-c(--context)、-e(--ed)、-n(--normal)、-u(--unified)のいずれかで形式を指定した場合は、その指定を優先します。コンテキスト差分(旧形式、新形式、unified形式)と通常形式の差分はpatch自身が適用します。ed形式の差分は、パイプでed(1)エディターに渡すだけです。

patchは、差分の前にある不要なテキストを読み飛ばしてから差分を適用し、その後にある不要なテキストも読み飛ばそうとします。そのため、差分リストを含むメールのメッセージをそのままpatchに渡しても動作するはずです。差分全体が一定量インデントされている場合、行がCRLFで終わる場合、またはInternet RFC 934の規定に従い、-で始まる行に- を1回以上付けて差分がカプセル化されている場合は、それらを考慮します。インデントやカプセル化を取り除いた後、#で始まる行はコメントとみなして無視します。

コンテキスト差分では、また適用できる範囲はそれより狭いものの通常形式の差分でも、patchはパッチに記された行番号の誤りを検出し、各ハンク(変更のまとまり)を適用する正しい位置を探そうとします。最初の候補位置は、ハンクに記された行番号に、直前のハンクを適用したときのオフセットを加減した位置です。その位置が正しくなければ、ハンクのコンテキストに一致する一連の行を前後に探します。まず、コンテキストのすべての行が一致する位置を探します。見つからず、かつコンテキスト差分で最大曖昧度(fuzz factor)が1以上なら、コンテキストの最初と最後の行を無視して再び探します。それでも見つからず、最大曖昧度が2以上なら、コンテキストの最初と最後の2行ずつを無視して再び探します。最大曖昧度の既定値は2です。

曖昧度を適用した後、前側のコンテキストが後側より少ないハンクは、先頭の行番号が1ならファイルの先頭に適用しなければなりません。前側のコンテキストが後側より多いハンクは、ファイルの末尾に適用しなければなりません。

ハンクを適用できる位置が見つからなければ、patchはそのハンクをrejectファイルに出力します。通常、その名前は出力ファイル名に.rejを付けたものです。.rejを付けると名前が長すぎる場合は、代わりに#を付けます。1文字の#を付けても長すぎる場合は、ファイル名の最後の文字を#に置き換えます。

拒否されたハンクは、unified形式またはコンテキスト形式の差分として出力します。入力が通常形式の差分だった場合、多くのコンテキストは空になります。rejectファイル内のハンクの行番号は、パッチファイル内の行番号と異なることがあります。これは、適用に失敗したハンクが元のファイルではなく変更後のファイルのどのあたりに入るとpatchが考えたかを示します。

ハンクごとの処理が終わるたびに、失敗したかどうかを通知します。失敗した場合は、patchがそのハンクを挿入すべきだと考えた変更後のファイルの行番号も通知します。差分に指定された行番号とは別の行に適用した場合は、オフセットを通知します。1回でも大きなオフセットがあれば、ハンクを誤った場所に適用した可能性があります。一致させるために曖昧度を使用した場合も通知します。その場合も、少し疑ってみるべきです。--verboseオプションを指定すると、完全に一致したハンクについても通知します。

コマンドラインで元のファイルorigfileを指定しなかった場合、patchは差分の前にあるテキストから、編集するファイル名を次の規則で推測します。

まず、ファイル名の候補を次のように順序付きで収集します。

  • コンテキスト差分のヘッダーであれば、ヘッダー内の変更前と変更後のファイル名を取得します。-p numまたは--strip=numオプションで必要とされる数のスラッシュがない名前は無視します。/dev/nullという名前も無視します。
  • 差分の前にIndex:行があり、変更前と変更後の名前がどちらも存在しない場合、またはpatchがPOSIXに準拠している場合は、Index:行にある名前を取得します。
  • 以下の規則では、ヘッダー内の出現順序にかかわらず、候補のファイル名を(変更前、変更後、index)の順序で扱います。

次に、候補のリストからファイル名を次のように選びます。

  • 候補のうち存在するファイルがあれば、POSIXに準拠している場合は最初の名前を、それ以外の場合は最適な名前を選びます。
  • RCS、ClearCase、Perforce、SCCSを無視しておらず(-g numまたは--get=numを参照)、候補のファイルはどれも存在しないものの、RCS、ClearCase、Perforce、SCCSのマスターが見つかった場合は、そのようなマスターがある最初の候補名を選びます。
  • 候補のファイルがどれも存在せず、RCS、ClearCase、Perforce、SCCSのマスターも見つからず、名前の候補はあり、patchがPOSIXに準拠しておらず、かつパッチがファイルを作成するものと考えられる場合は、必要なディレクトリの新規作成数が最も少ない最適な名前を選びます。
  • 以上の経験則でファイル名が決まらなければ、パッチを適用するファイル名をユーザーに尋ね、入力された名前を選びます。

空でない候補リストから最適な名前を決めるには、まずパス名の構成要素が最も少ない名前をすべて選びます。その中からベース名が最も短いものをすべて選び、さらにその中から名前全体が最も短いものをすべて選びます。最後に、残った名前のうち最初のものを選びます。

また、差分の前にPrereq:行があれば、patchはその前提条件の行の最初の単語(通常はバージョン番号)を取得し、元のファイルにその単語が含まれているか調べます。見つからなければ、処理を続ける前に確認を求めます。

このため、次のようなシェルコマンドを実行すれば、

patch -d /usr/src/local/blurfl

標準入力から読み込んだパッチを使い、blurflディレクトリ内のファイルへ直接パッチを適用できるはずです。

パッチファイルに複数のパッチが含まれている場合、patchはそれぞれが別々のパッチファイルから来たかのように適用しようとします。したがって、特に、差分リストごとに対象のファイル名を判定する必要があると想定します。また、先に述べたように、各差分リストの前にあるテキストには、ファイル名やリビジョンレベルなどの有用な情報が含まれていると想定します。