【diff/fc】2つのファイルの差分を表示 ~今週のコマンド005

1+

金曜連載

今週のコマンド

この連載ではUNIXライクなOS(Linux,Macなど)や、Windowsのコマンドプロンプトで使えるコマンドを週に数個ずつ、紹介します。

第5回となる今回は、要望が多かった2つの(テキスト形式)ファイルの差分を表示するコマンド diff/fc を紹介します。diffコマンドの出力はなかなかにわかりにくいので、できるだけわかりやすく丁寧に解説していこうと思います。

ページ内ジャンプ

diffコマンド(Linux,Mac)fcコマンド(Windows)

 

構文(Linux,Mac)

Linux diff [オプション] [ファイル1] [ファイル2]

[ファイル1]と[ファイル2]の違いを表示します。[ファイル1,2]はディレクトリでも可能です。両ファイルが全く同じ内容の場合、コマンドを入力しても何も出力されません。

オプション

-a ファイルがテキスト扱いできなくても、1行ずつ比較を行う
-b スペースの数の違いを無視する(不完全な行も無視)
-c context形式※で出力する
-i 大文字と小文字を区別しない
-n RCS形式※で出力する
-q ファイル同士が違うかだけを報告する
-r ディレクトリを比較するとき、サブディレクトリも比較する
-s ファイルに違いがない場合も報告する
-u unified形式※で出力する
-T テキストの前にスペースでなくタブを出力する これにより行中でのタブによる桁揃えが揃って出力される

※形式についてはこの下で説明しています。

使用例

実行結果の見方/出力形式について

diffコマンドでは4つの出力形式を選択可能です。この例では下の2つのファイルを使用します。(行番号を表示しています。また変更点に着色しています。)

prog1.c prog2.c
01| #include <stdio.h>
02|
03| int pow(int x){
04| return x*x;
05| }
06|
07| int main(void){
08| int i = 5;
09| pow(i);
10|
11| printf(“Hello, world!\n”);
12| printf(“i=%d\n”,i);
13|
14| return 0;
15| }
01| #include <stdio.h>
02|
03| int pow(int x){
04| //power
05| return x*x;
06| }
07|
08| int main(void){
09| int i = 3;
10| pow(i*2);
11|
12| printf(“Hello, world!\n”);
13| printf(“i=%d\n”,i);
14|
15| }

normal形式

通常の形式です。なにもオプションを与えないとこれが出力されます。
※説明のために行番号を加えています。

A1| $ diff prog1.c prog2.c
A2| 3a4
A3| > //power
A4| 8,9c9,10
A5| < int i = 5;
A6| < int i = 3;
A9| > pow(i*2);
AA| 14d14
AB| < return 0;
AC| $

まず、A2行目の「3a4」が何を表しているかというと「[ファイル1]の3行目の直後に行を a(add,追加) して、その行が[ファイル2]の4行目にあたる」ということです。 そして03行目の「> //power」は追加された内容を示します。(「>」は[ファイル2]の内容ということを示す。ちなみに「<」は[ファイル1]の内容。)

続いて、A4行目の「8,9c9,10」が何を表すかというと「[ファイル1]の8~9行目が c(change,変更) されて、[ファイル2]の9~10行目の部分になった」ということです。そしてその下に該当部分が表示されています。(「8,9c9,10」だとわかりにくい人は脳内で「8~9 → 9~10」とかにしましょう。)

最後に、AA行目の「14d14」「[ファイル1]の14行目を d(delete,削除)して、それは[ファイル2]の14行目に消えたようにする」ということを示しています。(「14a14」の逆です。うまく言葉にできません) ここまでくればもうわかりますね。

context形式

オプション「-c」を指定するとこの形式で出力されます。

$ diff -c prog1.c prog2.c
*** prog1.c 2016-06-01 15:29:32.120199000 +0900
— prog2.c 2016-06-01 15:29:25.723266000 +0900
***************
*** 1,15 ****
#include <stdio.h>

int pow(int x){
return x*x;
}

int main(void){
! int i = 5;
! pow(i);

printf(“Hello, world!\n”);
printf(“i=%d\n”,i);

return 0;
}
— 1,15 —-
#include <stdio.h>

int pow(int x){
+ //power
return x*x;
}

int main(void){
! int i = 3;
! pow(i*2);

printf(“Hello, world!\n”);
printf(“i=%d\n”,i);

}
$

これはとてもわかりやすいですね。各行の左端に「!」がある行は[ファイル1]から[ファイル2]にかけて変更があった部分、「」がある行は[ファイル1]には存在したが[ファイル2]には存在しない部分(削除された部分)、「+」がある行は[ファイル1]には存在しなかったが[ファイル2]で追加された部分を表します。 短い文章の比較をするときはこの形式がわかりやすいかもしれないですね。

unified形式

unified形式だと以下のようになります。

$ diff -u prog1.c prog2.c
— prog1.c 2016-06-01 15:29:32.120199000 +0900
+++ prog2.c 2016-06-01 15:29:25.723266000 +0900
@@ -1,15 +1,15 @@
#include <stdio.h>

int pow(int x){
+ //power
return x*x;
}

int main(void){
int i = 5;
pow(i);
+ int i = 3;
+ pow(i*2);

printf(“Hello, world!\n”);
printf(“i=%d\n”,i);

return 0;
}
$

これもわかりやすいですね。これがcontext形式と違うところは、[ファイル1]と[ファイル2]の比較を同時に行っているところです。記号はcontext形式と同じですが変更(!)のあったところも追加(+)と削除(-)で表現しています。

RCS形式

オプションに「-n」を指定してRCS形式で出力すると以下のようになります。

$ diff -n prog1.c prog2.c
a3 1
//power
d8 2
a9 2
int i = 3;
pow(i*2);
d14 1
$

これはunified形式と同じで変更を「a(add,追加)」と「d(delete,削除)」で表しています。例えば「a3 1」は「3行目に1行追加」ということを意味します。その下に追加された行の内容を示しています。同じように「d8 2」は「8行目から2行削除」ということを意味しています。

その他の使い方

ファイル同士が異なるかどうかだけを示します。

$ diff -q prog1.c prog2.c
ファイル prog1.c と prog2.c は異なります
$

 

構文(Windows)

Windows fc [オプション] [ファイル1] [ファイル2]

2つのファイルを比較する

オプション

/A 違いがある部分をすべて表示せずに省略する
/C 大文字と小文字を区別しない
/LB[数字] [数字]行以上連続して違う行が現れた場合、処理を中断する
/N 行番号を表示する
/C 大文字と小文字を区別しない
/T タブをスペースに変更しない
/W 連続したタブやスペースを1つのスペースとして比較する

使用例

2つのファイルで変更があった行±1行をピックアップし、変更点を表示しています。

C:\dir>fc prog1.c prog2.c
ファイル prog1.c と PROG2.C を比較しています
***** prog1.c
int pow(int x){
return x*x;
***** PROG2.C
int pow(int x){
//power
return x*x;
*****

***** prog1.c
int main(void){
int i = 5;
pow(i);

***** PROG2.C
int main(void){
int i = 3;
pow(i*2);

*****

***** prog1.c

return 0;
}
***** PROG2.C

}
*****

C:\dir>


 

infoWindowsでバイナリファイルを比較

バイナリファイルを比較したい時ってありますよね。そんな時には「compコマンド」。

Windows comp [オプション] [ファイル1] [ファイル2]

オプション

/A 違いをASCII文字で表示する
/C ASCII文字の大文字と小文字を区別しない
/D 違いを10進数で表示する[デフォルト]
/L 違う場所の行番号を表示する
1+