PATCH(1)

名称
patch - diff ファイルをオリジナルのファイルに適用する

書式
patch [options] [origfile [patchfile]] [+ [options] [origfile]]...

ですが、たいていは以下のようにします。

patch <patchfile

解説
patch は、 diff プログラムによって生成された差分情報を含むパッチファイル を受け付け、オリジナルファイルにその差分を当てて、パッチ済みの バージョンを生成します。 パッチファイルが省略されるか、`-' が指定された場合は、標準入力から パッチ情報を受け付けます。従って、普通は、単に、

       patch <patchfile

とやるだけで実行されます。 デフォルト動作では、オリジナルは ".orig" の拡張子 (長いファイル名を扱えないシステムでは "~") を付けてバックアップとして残した上で、オリジナルファイルは、 パッチ済みのバージョンに置き換えられます。オプションによってオリジナルを バックアップする拡張子は変更できます。また、環境変数 SIMPLE_BACKUP_SUFFIX によって、拡張子の文字列を指定することもできます。

もし、バックアップファイルが既に存在していた場合は、新しい バックアップファイル名として、ファイル名本体の中で最初に出てくる英小文字の 部分を大文字に替えたものを使います。英小文字の部分がなかった場合は、 ファイル名の最初の 1 文字削除したものを使います。

-o オプションで出力する場所を指定した時も、もし、そこに既に同じファイル名の ファイルが存在していたら、前述の規則に従って、まずバックアップが作られます。

patch が最初に行う作業は、差分情報がどんな形式か判別することです。これは、オプション -c, -e, -n, -u などによって形式を指定することもできます。 context diff (これにはさらに、old-style, new-style, unified がある) および、normal diff は patch によりパッチが当てられます。ed diff だった場合は、 patch は単にエディタ ed にパッチファイルをパイプを通して入力するだけです。

patch は、差分情報の前に含まれるゴミや、後に含まれるゴミは可能な限り スキップするようになっています。このため、 diff が生成した差分情報が入ったアーティクルやメッセージなども、 差分情報の部分だけを切り出すといった作業もなく、そのまま、 patch に与えることができます。また、差分情報の部分を 見易くするため、空白で段下げ (インデント) することも、段下げの幅が途中 で変わったりしなければ、受け付けできます。

context diff は、normal diff に比べ、差分情報に含まれるので多少 優秀 (違ってる部分だけでなく前後の一致部分も数行分含まれる patch では、 これを hunk と呼ぶ) で、差分情報の中の行番号が正しいかどうか検出し、 差分情報の中の一致部分も含めた差分内容が正しくなるようなパッチ場所を探します。 もし、正しい場所を見つけることができなかった場合は、その部分の差分情報 を hunk 単位でリジェクトファイルに出力します。レジェクトファイルは、通常、 出力すべきファイルに ".rej" の拡張子 (長いファイル名を扱えないシステムでは "#") を付けたものになります。このリジェクトファイルに出力 される時の差分情報に付けられている行番号は、元のパッチファイルのあるもの と違ったものになっている可能性もありますが、元のものよりは場所的により 近い位置になっていると思われる行番号になります。

patch は、パッチの進行状況を、hunk 単位で succeeded もしくは failed として報告します。

もし、オリジナルファイルがコマンドラインで指定されなかった場合、 patch は、エディットすべきファイル名を、差分情報の前に付加されているゴミの中 から見つけようとします。context diff のヘッダーの場合、ファイル名は、 "***" もしくは "---" で始まる行から探します。 context diffには、このような行しかありませんが、もし、 "Index:" いう行があったら、ここから得たファイル名を使うことを試みます。 もし、ファイル名を見つけることができなかった場合は、 パッチすべきファイル名を入力するよう求めます。

もし、オリジナルファイルが見つからないか、リードオンリーであるけれども、 SCCS か RCS ファイルあった場合、 patch は、SCCS からのゲットもしくは RCS からのチェックアウトを試みます。

加えて、もし、差分の前のゴミの中に、"Prereq: " という行が含まれて いたら、 patch は、その行に必要条件 (通常はバージョン番号) が書いてあるものと みなして最初の word を取りだし、オリジナルファイルの中に同じ word があるか どうか調べます。もしその word が発見できなければ、 patch は処理を実行してよいか、確認を求めるようになります。

ある news リーダーではパッチを含んだ記事において、

    | patch -d /usr/src/local/blurfl

のように指示することで、ディレクトリ blurfl にあるファイルにパッチをあ てることができます。

パッチファイルに、1 つ以上のパッチが含まれていた場合、 patch は、各々が 別々のパッチファイルであるものと思って処理を実行します。この場合、パッ チを当てるべきオリジナルファイルは、今まで説明したように、各々の差分情 報の中から抽出できると仮定しています。この他に、'+' で繋げてファイル名 を並べることで、2 番目以降のファイル名を指定することもできます。 (ただし、この場合でも、パッチ当てた後の新しいファイル名は指定することは できません)

patch には次のようなオプションがあります。

-bextension
    オリジナルをバックアップするファイル名に付ける拡張子を extension で指定します。

-Bprefix
    オリジナルをバックアップするファイル名の前に付ける記号 を prefix で指定します。この指定をすると、 -b の指定は無視されます。

-c  差分情報が context diff 形式であるものとみなします。

-e  差分情報が ed script 形式であるものとみなします。

-n  差分情報が normal diff 形式であるものとみなします。

-u  差分情報が context diff の unidiff 形式であるものとみなします。

-ddirectory
    処理の前に、directory で指定したディレクトリに移動します。

-Dsymbol
    symbol で指定したシンボルを定義します。これは、パッチファイルの中に、 C のプリプロセッサのように、 "#ifdef...#endif" を使った構文を用意して、シンボルによって差分情報を 切り替える時に使用できます。 なお、C コンバイラの指定と異なり、 -D と symbol の間には空白がなければなりません。

-E  パッチ処理後、空のファイルは削除するようにします。

-f  ユーザが、今、何をしているか正確に理解しているものと みなして、 patch からは何も尋ねず、次のように仮定して処理を進めます。

    パッチすべきオリジナルファイル見つけることができなかっ た場合はスキップします。

    ``Prereq:'' のバージョンが正しくなくても、パッチを実行します。

    パッチ済みと思われても、リバースパッチではないと仮定します。

    なお、このオプションは、 patch が表示するメッセージを止めません。メッセージを止めるには、 -s を使います。

-t  -f と同様ですが、次のように仮定します。

    パッチすべきオリジナルファイル見つけることができなかった場合は スキップします。( -f と同じ)

    ``Prereq:'' のバージョンが正しくない場合は、スキップします。

    パッチ済みと思われる場合は、リバースパッチと仮定します。

-Fnumber
    context diff で差分情報の中の行番号が正しくない時に 前後を調べるファクターを指定します。デフォルトは 2 で、これは、 context diff の一致行の行数 (通常は 3) より多くしない方がいいです。

-l  パターンマッチの条件を緩くし、タブおよび空白に関する違いは無視します。

-N  リバースパッチもしくは、すでにパッチ済みであると思われ る時には、スキップします。

-oout_file
    パッチを当てた出力ファイルを out_file とします。

-pnumber
    patch がパッチファイルから発見したパス名を元に、実際の ファイルを扱う時に、パス名の先頭からパスを取り除く数を number で指定します。パッチすべきファイルが複数のディレ クトリにまたがっており、パッチファイルを作った人の環境と、 自分の環境が異なっている場合に有効です。 例えば、 patch が見つけてきたパス名が

        /u/howard/src/blurfl/blurfl.c

    であった場合、 -p を何も指定しなかった場合は、ディレクトリ部分なしで最後のファイル名の部分 blurfl.c だけとなりますが、 -p1 と指定した場合、最初のパス名部分を除いた

        u/howard/src/blurfl/blurfl.c

    として扱います。 -p4 なら、

        blurfl/blurfl.c

    となります。 -p もしくは -p0 なら、そのまま、

        /u/howard/src/blurfl/blurfl.c

    というパス名が使われます。

-rrej_file
    リジェクトファイル名として rej_file を指定します。

-R  古いファイルと新しいファイルを間違えて差分情報を作って しまった場合のパッチファイル (リバースパッチと呼ぶ) に 適用します。ただし、ed script は情報が少な過ぎるの で使えません。

    patch は、パッチファイルの差分情報の最初の hunk のパッチに失敗した場合、 リバースパッチが適用できるか調べます。 そして、もし、リバースパッチができるようなら、ユーザに、 -R オプションをセットしたいかどうか尋ねます。 リバースパッチができないようなら、スキップして、通常の パッチを続けます。

-s  エラー以外のメッセージを表示しないようにします。

-S  パッチファイルからの現在の差分情報に関するパッチを 無視すようにします。 例えば、次のように指定した場合、

        patch -S + -S + <patchfile

    最初と 2 番目のファイルに関する差分情報は無視しますが 3 番目のファイルにはパッチを当てます。

-v  リビジョンヘッダーとパッチレベルを表示します。

作者
Larry Wall <lwall@netlabs.com>
および、その他の多くの貢献者たち。

環境変数

TMPDIR
    テンポラリファイルを置くディレクトリ。デフォルトでは、/tmp

SIMPLE_BACKUP_SUFFIX
    バックアップファイルに付ける拡張子を指定する。デフォルトでは、 ".orig" もしくは "~"。

関連ファイル
$TMPDIR/patch*

関連項目
diff(1)

診断
メッセージ "Hmm..." は、パッチファイルの中に差分情報でないために patch がスキップしているテキストがあることを示します。

リジェクトファイルが作られた時には、0 でない値を返します。

注意
パッチは、極力正しくパッチが当たるように処理しますが、必ず正しくなると保 証できるのは、パッチファイルを作った時と正確に同じバージョンのファイル に対してパッチを適用した時だけです。