diff コマンド

2つのテキストファイルの差分を抽出するコマンド。 2つのファイルの内容が一致しているかどうかをチェックする目的でも使える。

編集前のファイルをバックアップしておけば、編集後のファイルとバックアップとをdiffすることで、編集した箇所を確認できる。まあ、そんなことしなくても git や svn などのバージョン管理を使っていれば、差分は確認できるが。

diffコマンドをブラウザで使えるウェブアプリもあるようだ。

テキスト比較ツール difff《デュフフ》
http://difff.jp/

基本的な使い方

2つのファイル名を引数で渡すと、差分が標準出力される。

$ diff -u foo.txt bar.txt

片方のファイル名として - と書くと、標準入力が使われる。

$ foocmd | diff -u - bar.txt
スポンサーリンク

オプション

a
バイナリファイルと認識されてしまうファイルも強制的にテキストファイルの扱いにする
-u
差分をunified形式というフォーマットで表示する。git diff で表示されるフォーマットもunified形式な気がする。 慣れの問題かもしれないが、自分はこの形式が一番見やすくてaliasの設定をしている。
alias diff='diff -u'
-U 数字
差分の前後を表示する行数を指定してunified形式で表示する。-u だけの場合はデフォルトの3行を表示する。 git diff でも同じオプションが使える。
-b
連続する空白の長さの違いは無視する。たぶんgit diff-b オプションと同じ。
-i
大文字小文字の違いを無視する。
-w
-b と同じだが、空白の定義がこっちのほうが広い。タブとか?。たぶんgit diffのオプションと同じ。
-B
空行は無視する
-r
2つのディレクトリを再帰的にたどって、すべてのファイルを比較する
-q
差分のあったファイル名のみを表示し、差分の内容は表示しない。-r と組み合わせでよく使う。 git diffコマンドで同様のことをするには git diff --name-only または git diff --name-status とする。
--side-by-side
2つのファイルを横に並べて差分を表示する。sdiffコマンドと同じになる
-W <NUM>, --width=<NUM>
--side-by-side で表示の際の画面の横幅を指定する。デフォルトは130らしくて、 ターミナルを横長にして使いたい --side-by-side としては横幅が小さすぎる

HOWTO

標準入力(他のコマンドの出力)とファイルを比較するには

以下のように、 - を使うと、比較対象の片方を標準入力にすることができる。

$ cat foo.txt | diff bar.txt -

2つのコマンドの出力を比較するには

以下のようにすることで、2つのコマンドの出力をファイルに落とすことなく直接 diff にかけることができる。

$ diff <(cmd1 foo.txt) <(cmd2 bar.txt)

でもこれは、diff にとっては標準入力が2つ存在するわけではない。 bashやzshのプロセス置換の機能で、diff にとっては、 2つのファイルが引数として指定されている状態になる。

ちなみにdiffの代わりに引数の内容をそのまま表示してくれるecho

$ echo <(cmd1 foo.txt) <(cmd2 bar.txt)

とすると、/proc/self/fd/11 /proc/self/fd/12 のように出力される。 (2013/06/04: bash, zsh で動作確認済み)

2つのファイルを左右に並べて表示するには (sdiff)

$ diff --side-by-side foo.txt bar.txt

side-by-side出力形式というらしい。

diffコマンドの代わりにsdiff というコマンドを使ってもいいかも。

$ sdiff foo.txt bar.txt

シェルスクリプトで2ファイルが同じかどうかで分岐をさせるには

diff は2つのファイルが同じだった場合に成功の終了コード(0)を返し、違いがあった場合には異常終了(0以外)を返すので、以下のように書ける。

if diff -q fileA.txt fileB.txt >/dev/null ; then
    # 同じだった場合
else
    # 違っていた場合
fi

普通 diff を使うときというのは、2つのファイルの違う箇所を確認するときで、違いがあるの場合がほとんどなのに、違いがある方が異常終了で、全く同じなときに正常終了というのは、ちょっと直感に反する気がして、不思議。いや、考えようによってはどっちもありか。

ちなみに if の中に >/dev/null を付けないと、条件判定するたびにいちいち diff が標準出力にメッセージを出力してしまう。

差分表示をカラーで見やすく表示するには

colordiff というツールをインストールして使うとカラフルに表示させられるらしい。

## Ubuntuの場合のインストール
$ apt-get install colordiff

でもインストールするのが面倒なら、colordiffでなくて代わりにgitコマンドを使ってもよい。 gitなら、普段作業している環境にはたいてい入れている人が多いと思うので。

gitコマンドは git diff ... でgit管理下にあるファイルの差分を表示してくれるが、 git diff --no-index ... とすると、リポジトリと関係なく任意の2つのファイルの差分を表示してくれる便利機能がある。

gitコマンドでファイルの差分を表示させると、ちゃんと設定してあれば、色付きで表示してくれるし、長い差分でもlessをパイプで手動でつなぐことなく自動でページャーで表示してくれて使いやすい。

$ colordiff -u fileA.txt fileB.txt

## gitを使う方法
$ git diff --no-index fileA.txt fileB.txt

git管理下でないディレクトリでは、--no-index を付けなくてもよい。

ただし、コマンド出力を比較したい場合は、git diff --no-index ではうまくいかない。以下のように表示されてしまう。

$ git diff --no-index <(cmd1 foo.txt) <(cmd2 bar.txt)
diff --git a/proc/self/fd/11 b/proc/self/fd/12
index 77ce113..e368dd3 120000
--- a/proc/self/fd/11
+++ b/proc/self/fd/12
@@ -1 +1 @@
-pipe:[19021782]
\ No newline at end of file
+pipe:[19021783]
\ No newline at end of file

#692857 - git diff –no-index: needs option to compare symlink targets instead of links (for example when comparing <() substitutions) - Debian Bug report logs

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。