UNIX/Linuxの部屋 patchコマンドの使い方


※空白区切りで AND 検索 (例:「ファイル 削除」)

コマンド patch パッチを当てる

「パッチ」とは、古いファイルと新しいファイルの差分のことで、「パッチを当てる」とは、古いファイルと差分データを参照しながら新しいファイルを作ることを指す。

パッチファイルを入手し、
% patch < パッチファイル
とすると自動的にパッチ当て作業が行われる。オリジナルのファイルは、.orig という拡張子を付けたファイルに保存される。ただし、patch に慣れていない場合は、カレントディレクトリをどこにするかに迷うであろう。カレントディレクトリが違うとパッチ当てに失敗するからである。

パッチファイルの先頭部分を見てみると、
*** file.txt.org Sun Sep 12 09:53:17 1999
--- file.txt Sun Sep 12 09:53:17 1999
や (これは context 形式)、
--- file.txt.org Sun Sep 12 09:53:17 1999
+++ file.txt Sun Sep 12 09:53:17 1999
となど (これは unified 形式)、ファイル名の情報が記録されているはずである。この例はディレクトリ名はなく、ファイル名のみが記録されているので、パッチを当てる対象の file.txt が置いてあるディレクトリに移動してからパッチを当てるとよい。例えば
--- src/file.txt.org Sun Sep 12 09:53:17 1999
+++ src/file.txt Sun Sep 12 09:53:17 1999
なら、src ディレクトリの中ではなく、その一つ上に移動してからパッチを当てる。つまり、
% ls 「パッチの先頭に書かれているファイル名」
として、ファイル名が表示されるようなディレクトリに移動してからパッチを当てなければいけない、ということである。

次にパッチを当てる際の出力について解説する。
% patch < patch.txt
Hmm... Looks like a unified diff to me...
これは、パッチの種類を判別している。パッチにはいくつか種類があるが、普通 unified 形式か、context 形式が使われる (詳細は diff コマンドの項を参照)。つまり、
Hmm... Looks like a unified diff to me...
Hmm... Looks like a new-style context diff to me...
いずれかの出力ならば問題はない。しかし
Hmm... Looks like a normal diff to me...
のように、unified 形式でも context 形式でもない場合は、パッチ自体にファイルの情報が含まれていないので、パッチを当てるファイルを入力しなければならない。おそらくパッチ作成者のミスであろう。もし、
File to patch:
いう出力があった場合は、ユーザはパッチを当てるファイル名を入力するよう求められている。これは
  • パッチが context 形式でも unified 形式でもないので、どのファイルにパッチを当てたらよいのかわからない。
  • ファイルが見付からない (あるいはあなたの手元には、本当にパッチを当てるべきファイルが無いのかもしれない)。
という原因が考えられる。ファイルが見付からない場合、先に書いたようにパッチファイルに記録されたファイル名を見て、カレントディレクトリを移動しなければならない。

リバースパッチ
Reversed (or previously applied) patch detected! Assume -R? [y]
という出力があった場合は、
  • リバースパッチである
  • 既にそのパッチは当ててある
のいずれかである。diff コマンドでパッチを作る際、ファイルの引数を逆にしてしまうと、リバースパッチと呼ばれる正反対のパッチが作成される。これが原因ならば、
Assume -R? [y]
のところで「y」かリターンキーをタイプすると、リバースパッチとみなしてパッチを当てる。あるいは、あなたが過去にそのパッチを当てていることを忘れてしまい、再度同じパッチを当てようとしているかもしれない。その場合は「y」を選ぶと過去のバージョンに戻ってしまう。

オプション
-C 処理内容を表示するが、実際にはパッチを当てない。
まず最初はこのオプションを付けて実行すること。
-R パッチをリバースパッチと見なす。
最初からリバースパッチとわかっている場合は、-R オプションを付けることで
Reversed (or previously applied) patch detected! Assume -R? [y]
という問い合わせをせずに、パッチ当て作業を自動的に行う。
-N リバースパッチと思われるパッチをスキップする。

余談
なお patch コマンドは、パッチファイルの最初や最後にゴミが含まれていても自動的にスキップしてくれるので、NetNews のヘッダや、先頭にパッチの説明が入ったファイルでも気にせずパッチが当てられる。また、パッチ全体にインデントが付いていても自動的に認識する。さすがは Larry Wall (Perl の作者) が作ったプログラム。便利だ。

パッチファイルを作成するには diff を使う。
>> Linuxオンラインマニュアル(man) Linux patch(1)
>> FreeBSDオンラインマニュアル(man) FreeBSD patch(1)


頑張って書いたおすすめコンテンツ!
クラウドサービス徹底比較・徹底解説