patchコマンドは、diffコマンドで作成したパッチファイルをファイルに適用します。
パッチファイルは、一つのファイルに適用することもできますが、パッチファイルの内容の形式によっては、ディレクトリにあるファイルごとパッチを適用できます。
目次
patchコマンドの基本的な構文
patchコマンドの基本的な構文
1 |
patch [option]... [file [patchfile]] |
patchコマンドはパッチファイルを標準入力から読み込むことができます。その場合、リダイレクト等が利用できます。
1 |
patch < patchfile |
diffコマンドで作成できるpatchファイルの形式
patchコマンドで使用できるパッチファイルで利用できる形式には様々な形式があります。ここでは、diffコマンドで出力をファイルに保存して、patchコマンドを利用します。diffコマンドで出力される形式は主に以下のような形式があります。
normal形式の例
1 2 3 4 5 |
$diff oldfile.c newfile.c 5c5 < printf("patch test oldfile.txt\n"); --- > printf("patch test newfile.txt\n"); |
context形式の例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$diff -c oldfile.c newfile.c *** oldfile.c 2018-04-04 12:33:47.704894999 +0900 --- newfile.c 2018-04-04 12:34:09.595835000 +0900 *************** *** 2,7 **** int main() { ! printf("patch test oldfile.txt\n"); return 0; } --- 2,7 ---- int main() { ! printf("patch test newfile.txt\n"); return 0; } |
unified形式の例
1 2 3 4 5 6 7 8 9 10 11 |
$diff -u oldfile.c newfile.c --- oldfile.c 2018-04-04 12:33:47.704894999 +0900 +++ newfile.c 2018-04-04 12:34:09.595835000 +0900 @@ -2,6 +2,6 @@ int main() { - printf("patch test oldfile.txt\n"); + printf("patch test newfile.txt\n"); return 0; } |
patchコマンドを利用する場合、normal形式のパッチファイルにはファイル名の情報がないため、パッチを適用するためにはファイルを指定する必要があります。
context形式やunified形式にはファイル名の情報があるため、パッチファイルを読み込むことでパッチをファイルに適用することもできます。
patchコマンドの利用例
ファイルにパッチを適用
patchコマンドでファイルとパッチファイルを指定することで、そのファイルがパッチファイルを適用できる場合、そのファイルの内容が書き換わります。
また、ファイルの内容は書き換えられるため、バックアップがほしい場合は-bオプションを利用することで、バックアップを作成した後にファイルにパッチを適用できます。
oldfile.c
1 2 3 4 5 6 7 |
#include <stdio.h> int main() { printf("patch test oldfile.txt\n"); return 0; } |
newfile.c
1 2 3 4 5 6 7 |
#include <stdio.h> int main() { printf("patch test newfile.txt\n"); return 0; } |
cfile_normal.patch(diffコマンドの出力)
1 2 3 4 |
5c5 < printf("patch test oldfile.txt\n"); --- > printf("patch test newfile.txt\n"); |
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 |
$patch oldfile.c cfile_normal.patch patching file oldfile.c $cat oldfile.c #include <stdio.h> int main() { printf("patch test newfile.txt\n"); return 0; } |
unified形式等ファイル情報があるパッチファイルの場合、パッチファイルをpatchコマンドへ標準入力から読み込ませることで、そのファイルパスを読み込んでパッチを適用することができます。
cfile_unified.patch
1 2 3 4 5 6 7 8 9 10 |
--- oldfile.c 2018-04-04 13:18:51.119926999 +0900 +++ newfile.c 2018-04-04 12:34:09.595835000 +0900 @@ -2,6 +2,6 @@ int main() { - printf("patch test oldfile.txt\n"); + printf("patch test newfile.txt\n"); return 0; } |
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ls cfile_unified.patch oldfile.c $ $patch < cfile_unified.patch patching file oldfile.c $ $cat oldfile.c #include <stdio.h> int main() { printf("patch test newfile.txt\n"); return 0; } |
また、ファイル情報のあるunified形式等のパッチファイルは、normal形式のパッチファイルと同じようにファイルを指定して、パッチを適用することもできます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 |
$patch oldfile_another.c cfile_unified.patch patching file oldfile_another.c $cat oldfile_another.c #include <stdio.h> int main() { printf("patch test newfile.txt\n"); return 0; } |
パッチを適用できるか確認
(--dry-runオプション)
--dry-runオプションを利用すると、パッチを適用する前にファイルにパッチを適用することができるかを確認できます。
コマンド例と実行結果
1 2 |
$patch --dry-run oldfile.c cfile_unified.patch checking file oldfile.c |
失敗する場合は、エラーメッセージが表示されます。
コマンド例と実行結果
1 2 3 4 |
$patch --dry-run nofile.c cfile_unified.patch checking file nofile.c Hunk #1 FAILED at 2. 1 out of 1 hunk FAILED |
バックアップを作成
(-bオプション)
-bオプションを用いると、パッチを適用する前にファイルのバックアップを作成できます。デフォルトのバックアップファイルの名前は元のファイル名に接尾辞として基本的に.origがつきます。
コマンド例と実行結果
1 2 3 4 5 6 |
$ls cfile_unified.patch oldfile.c $patch -b oldfile.c cfile_unified.patch patching file oldfile.c $ls cfile_unified.patch oldfile.c oldfile.c.orig |
-bオプションに対して、-zオプションを追加するとバックアップファイルの接尾辞を変更できます。
コマンド例と実行結果
1 2 3 4 5 6 |
$ls cfile_unified.patch oldfile.c $patch -b -z.bak oldfile.c cfile_unified.patch patching file oldfile.c $ls cfile_unified.patch oldfile.c oldfile.c.bak |
-Bオプションを利用すると指定しているファイル名の始めに文字をつけることができます。また、-Bオプションは保存するディレクトリを指定することもできます。
コマンド例と実行結果(ファイル名の始めに文字をつける)
1 2 3 4 5 6 |
$ls cfile_unified.patch oldfile.c $patch -b -B backup- oldfile.c cfile_unified.patch patching file oldfile.c $ls backup-oldfile.c cfile_unified.patch oldfile.c |
コマンド例と実行結果(保存するディレクトリを指定)
1 2 3 4 5 6 |
$ls backupdir cfile_unified.patch oldfile.c $patch -b -B backupdir/ oldfile.c cfile_unified.patch patching file oldfile.c $ls backupdir/ oldfile.c |
下のコマンド例では、-Yオプションと-Bオプションでbackupというディレクトリを作成しバックアップファイルを保存しています。
また、-Rオプションはパッチを戻すオプションになります。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
$tree . └── dir ├── cfile_unified.patch └── oldfile.c 1 directory, 2 files $patch -b -Y backup/ dir/oldfile.c dir/cfile_unified.patch patching file dir/oldfile.c $tree . └── dir ├── backup │ └── oldfile.c ├── cfile_unified.patch └── oldfile.c 2 directories, 3 files $patch -R dir/oldfile.c dir/cfile_unified.patch patching file dir/oldfile.c $patch -b -B backup/ dir/oldfile.c dir/cfile_unified.patch patching file dir/oldfile.c $tree . ├── backup │ └── dir │ └── oldfile.c └── dir ├── backup │ └── oldfile.c ├── cfile_unified.patch └── oldfile.c 4 directories, 4 files |
ディレクトリにあるそれぞれのファイルに対してパッチを適用
(-pオプションと-dオプション)
ディレクトリに対して、パッチを適用する場合は-pオプションが重要になります。
-pオプションは数字を指定して、指定した数字の分だけパッチファイルでのファイルパスにあるディレクトリの部分を削除できます。
パッチファイルで適用するファイルが'v1/point.txt'のようなファイルパスの場合、-p0オプションを指定すると'v1/point.txt'のファイルに対して、パッチを適用します。
-p1オプションを指定すると'point.txt'というファイルに対して、パッチを適用します。
-pオプションを指定しない場合は、全てのディレクトリ部分を除いた、ファイル名の部分だけのファイル('v1/point.txt'ならば、'point.txt'のファイル)に対して、パッチを適用します。
v1のディレクトリ(パッチを適用するディレクトリ)
1 2 3 4 5 6 7 8 9 |
$tree v1 v1 ├── README ├── point-v1.txt ├── point.txt -> point-v1.txt └── subdir └── subdir_file.txt 1 directory, 4 files |
v1_dir.patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
diff -ur v1/README v2/README --- v1/README 2018-04-05 16:36:45.562579001 +0900 +++ v2/README 2018-04-05 16:36:45.562579001 +0900 @@ -1 +1 @@ -v1 point table directory +v2 README directory Only in v1: point-v1.txt Only in v2: point-v2.txt diff -ur v1/point.txt v2/point.txt --- v1/point.txt 2018-04-05 16:36:45.562579001 +0900 +++ v2/point.txt 2018-04-05 16:36:45.562579001 +0900 @@ -1,4 +1,6 @@ -number,name,point +no.,name,point 1,aaa,100 -2,ccc,80 -3,eee,90 +2,bbb,28 +3,ccc,80 +4,ddd,65 +5,eee,90 diff -ur v1/subdir/subdir_file.txt v2/subdir/subdir_file.txt --- v1/subdir/subdir_file.txt 2018-04-05 16:36:45.562579001 +0900 +++ v2/subdir/subdir_file.txt 2018-04-05 16:36:45.562579001 +0900 @@ -1 +1 @@ -v1 subdir file +v2 subdir file Only in v2: v1 |
コマンド例と実行結果
1 2 3 4 5 |
$patch -p0 < v1_dir.patch patching file v1/README File v1/point.txt is not a regular file -- refusing to patch 1 out of 1 hunk ignored -- saving rejects to file v1/point.txt.rej patching file v1/subdir/subdir_file.txt |
シンボリックリンクファイルに対して、--follow-symlinksオプションを指定していない場合は、シンボリック先のファイルに対してパッチを適用することはできません。
パッチを適用できなかった場合はreject fileが作成されます。reject fileはパッチを適用できなかったところのパッチが出力されます。また、reject fileのデフォルトの拡張子は.rejになります。
reject fileの内容例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$cat v1/point.txt.rej --- v1/point.txt 2018-04-05 16:36:45.562579001 +0900 +++ v2/point.txt 2018-04-05 16:36:45.562579001 +0900 @@ -1,4 +1,6 @@ -number,name,point +no.,name,point 1,aaa,100 -2,ccc,80 -3,eee,90 +2,bbb,28 +3,ccc,80 +4,ddd,65 +5,eee,90 |
また、-dオプションを指定すると、パッチを適用するディレクトリを指定することができます。
コマンド例と実行結果
1 2 3 4 |
$patch -p1 -d v1 --follow-symlinks < v1_dir.patch patching file README patching file point.txt patching file subdir/subdir_file.txt |
パッチが適用済みのファイルを無視
(-Nオプション)
-Nオプションはパッチファイルがすでに適用済みのファイルやパッチを逆に適用するファイルを無視します。
ここでは、パッチをディレクトリに適用するときに--follow-symlinksをつけ忘れたものに再びパッチを適用しています。
コマンド例と実行結果
1 2 3 4 5 6 7 8 |
$patch -p0 --follow-symlinks -N < v1_dir.patch patching file v1/README Reversed (or previously applied) patch detected! Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file v1/README.rej patching file v1/point.txt patching file v1/subdir/subdir_file.txt Reversed (or previously applied) patch detected! Skipping patch. 1 out of 1 hunk ignored -- saving rejects to file v1/subdir/subdir_file.txt.rej |
パッチファイルを指定
(-iオプション)
-iオプションは適用するパッチファイルを指定することができます。-iオプションが指定されていない場合は、標準入力からパッチファイルを読み込むことができます。
コマンド例と実行結果
1 2 3 4 |
$patch -i v1_dir.patch -p0 --follow-symlinks patching file v1/README patching file v1/point.txt patching file v1/subdir/subdir_file.txt |
パッチを戻す
(-Rオプション)
-Rオプションは、パッチを適用したファイルを戻すときやdiffコマンドで引数を逆にして作成してしまったパッチファイルを適用する場合に利用できます。
oldfile.c(パッチ適用済み)
1 2 3 4 5 6 7 |
#include <stdio.h> int main() { printf("patch test newfile.txt\n"); return 0; } |
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 |
$patch -R oldfile.c cfile_unified.patch patching file oldfile.c $cat oldfile.c #include <stdio.h> int main() { printf("patch test oldfile.txt\n"); return 0; } |
参考
GNU diffutils - Comparing and Merging Files