diff(ディフ)とは
diffは、2つのファイル間の差異を比較し、その結果を出力するコマンドラインツールです。
テキストファイルだけでなく、最近の実装ではバイナリファイルの比較もサポートしています。diffコマンドの出力は、変更箇所を特定するだけでなく、`patch`コマンドで適用できる形式であるため、ファイルの差分を管理する上で非常に重要です。また、diffコマンド以外で生成された差分も一般的に「diff」と呼ばれます。
歴史
diffコマンドは、1970年代初頭に
AT&Tベル研究所で開発され、1974年の
UNIX第5版に同梱されて初めて公開されました。ダグラス・マキルロイ氏が開発した最終バージョンは、ジェームズ・W・ハント氏との共同研究として発表されました。マキロイ氏の研究は、
スティーブ・ジョンソン氏のGCOS上の比較プログラムやマイク・レスク氏のproofプログラムに影響を受けています。初期のツールではヒューリスティクスが用いられていましたが、マキロイ氏はより堅牢で汎用的なツールを目指しました。
初期のdiffは、`ed`エディタの編集スクリプト機能と組み合わせることで、ファイル履歴を効率的に管理することができました。これにより、元のファイルと編集スクリプトを保存するだけで、変更後のファイルを再構成でき、ディスク容量を大幅に削減できました。ラリー・ウォール氏は、diffの出力を入力としてファイルを変更する`patch`コマンドを開発し、このアイデアを一般化しました。
当初、diffはソフトウェアのコードや文書の比較、デバッグ出力の検証、ファイルリストの比較などに使われていました。その後、ファイルへの変更をまとめることでファイル容量を節約する手法が生まれ、Source Code Control System(SCCS)などの
バージョン管理システムに採用されました。
diffの概念は、ザナドゥ計画の「相互参照ウィンドウ」機能に影響を受けており、ファイルの差分表示は「トランスクルージョン」という概念に含まれます。トランスクルージョンとは、ある文書が他の文書やその一部を含むことを意味します。また、電子化された人文科学分野では、過去の文学作品を比較するツールとしても活用されています。
使用法
diffコマンドは、以下のように2つの
ファイル名を指定して実行します。
bash
diff original new
このコマンドは、`original`ファイルを`new`ファイルに変更するために必要な箇所を表示します。ディレクトリを指定した場合は、両方のディレクトリに存在する各ファイルに対してdiffが実行されます。`-r`オプションを使用すると、サブディレクトリ内のファイルも比較できます。
利用例
以下は、`original`ファイルと`new`ファイル間のdiffの出力例です。
2,4c2,3
< this is the original file.
< This line should be deleted.
< another line in the old file.
> this is the new file.
the line after edit.
5d4
< last line in original file.
出力形式は、`a`(追加)、`d`(削除)、`c`(変更)を意味し、これらの文字の前に元のファイルでの行番号、後に変更後のファイルでの行番号が示されます。行頭の山括弧`>`は追加された行、`<`は削除された行を示します。
変種
diffの実装は、1975年以降ほとんど変わっていませんが、アルゴリズムの改善や便利な機能の追加、新しい出力形式の設計が行われています。基本的なアルゴリズムは、ユージン・W・マイヤーズ氏やウェッブ・ミラー氏によって研究されており、E.ウッコネン氏も独立して同様のアルゴリズムを発見しています。
最初のdiffは
テキストファイルの行単位での比較を目的としていましたが、1980年代までにはバイナリファイルの対応も追加されました。`sdiff`はdiff項目を並べて出力し、`diffmk`は印刷文書の変更箇所をマークします。バークレー版
UNIXでは、コンテキスト形式(`-C`)とディレクトリ構造を再帰的に辿る機能(`-r`)が追加されました。特にコンテキスト形式は、パッチ形式での配布を促進しました。
`diff3`は、1つのファイルを他の2つのファイルと比較するために使用され、主に`merge`プログラムから呼び出されます。`Wdiff`はテキスト中の単語単位やフレーズ単位での変更を表示し、`Spiff`は浮動小数点数の精度やコメントなどを無視した比較ができます。
コンテキスト形式(Context format)
コンテキスト形式では、変更された行の前後数行も表示されます。これにより、変更箇所をパッチに適用する際のコンテキストが提供され、人間にとっても読みやすくなります。コンテキスト形式は、パッチプログラムへの入力として使用されます。
変更箇所の上下に表示する行数は指定できますが、デフォルトでは3行です。変更箇所の提示部分で重複する非変更行はまとめられます。「!」は変更された行、「+」は挿入された行、スペースで始まる行は非変更行を示します。パッチの先頭行にはファイル情報が記載され、変更箇所には対応する行番号が示されます。
ユニファイド形式 (Unified format)
ユニファイド形式は、コンテキスト形式の改良版であり、よりコンパクトで読みやすい形式です。`-u`オプションで指定され、パッチ形式での出力に広く使われています。
ソフトウェア開発者の間では、パッチを投稿する際の共通形式となっています。
ユニファイド形式では、ヘッダ行はコンテキスト形式と同様ですが、元ファイルは`---`、新ファイルは`+++`で示されます。変更箇所はスペース(非変更)、`+`(挿入)、`-`(削除)で始まる行で示されます。変更範囲は、`@@ -R +R @@`の形式で示され、Rは`l,s`の形式で変更箇所の開始行と行数を表します。変更された行は削除+挿入として表示されます。
実装
GNU Diffutilsには、`cmp`、`diff`、`diff3`、`patch`などのツールが含まれています。
関連項目
編集距離
差分符号化
rsync
マージ(
バージョン管理システム)
参考文献
Paul Heckel (1978). “A technique for isolating differences between files”. Communications of the ACM 21 (4): 264-268.
James W. Hunt and M. Douglas McIlroy (1976). “An Algorithm for Differential File Comparison”. Computing Science Technical Report, Bell Laboratories 41.
David MacKenzie, Paul Eggert, and Richard Stallman (1997). Comparing and Merging Files with GNU Diff and Patch. ISBN 0-9541617-5-0
E. Myers (1986). “An O(ND) Difference Algorithm and Its Variations”. Algorithmica 1 (2): 251-266.
Webb Miller and Eugene W. Myers (1985). “A File Comparison Program”. Software ― Practice and Experience 15 (11): 1025-1040.
E. Ukkonen (1985). “Algorithms for Approximate String Matching”. Information and Control 64: 100-118.
外部リンク
GNU Diff utilities - Free Software Foundation提供
オンライン版diffプログラム
difff《デュフフ》 - 日本語対応で簡単に差分が確認できるテキスト比較ツール
diffj -
Java用のdiffライブラリ