Linux / コマンド / diff - テキストファイルとディレクトリの違いを比較
diffは、2つのテキストファイルまたはディレクトリを比較して、異なる部分を表示するコマンドです。特に-uのunified diff形式は、変更前後の文脈を一緒に提供するため、パッチやコードレビューで広く使用されます。
この記事ではdiffの基本的な文法と主なオプション、実際の使用例、関連コマンドとの違い、使用時の注意点について説明します。
diffコマンドとは?
1つ目から2つ目へどの行が変わったかを差分として計算します。終了状態は、指定した比較条件で差分がなければ0、差分があれば1、GNU版の比較エラーは通常2です。標準出力が空でもエラーがないとは限らないため、診断と終了状態も確認してください。空白を無視するオプションを使った場合の「差分なし」は、バイト単位で同一という意味ではありません。
基本的な文法
diff [オプション] ファイル1 ファイル2
diff [オプション] ディレクトリ1 ディレクトリ2
オプションや詳細な動作は実装やバージョンによって異なる場合があります。現在のシステムではdiff --helpとman diffでインストールされたコマンドの説明を確認してください。
diffの基本的な使い方
2つのファイルを比較する
基本的な出力は変更コマンドの形式で表示されます。
diff old.conf new.conf
unified形式で比較する
変更行の前後の文脈が一緒に表示され、人が読みやすくなります。
diff -u old.conf new.conf
ディレクトリを再帰的に比較する
対応するサブパスまで再帰的に比較します。ファイルの内容や存在の差を調べるもので、所有権や権限の一致まで保証しません。属性はstatによるファイル情報の確認も併用します。GNU版では通常リンク先を比較するため、リンク自体を比較したい場合は対応する --no-dereference を確認してください。
diff -ru project-old project-new
変更表示と終了ステータスの読み取り
diff -uは二つのファイルの異なる行をunified形式で表示します。以下の例では、最初のファイルのoldが二番目のファイルのnewに変更されました。
printf 'old\n' > before.txt
printf 'new\n' > after.txt
diff -u before.txt after.txt
出力の主要部分(ファイルヘッダーの時刻は省略):
-old
+new
-は最初のファイルにのみある行、+は二番目のファイルにのみある行です。二つのファイルが異なる場合、終了ステータスは1であり、これを実行失敗ステータス2と区別してください。
主なオプション
| オプション | 説明 |
|---|---|
-u |
unified形式で文脈と差分を出力します。 |
-r, --recursive |
サブディレクトリを再帰的に比較します。 |
-q, --brief |
詳細な差異の代わりに異なるかどうかだけを報告します。 |
-s, --report-identical-files |
同一のファイルも明示的に報告します。 |
-w, --ignore-all-space |
行内の空白の有無や量を無視します。行の区切りそのものを無視する指定ではありません。 |
-b, --ignore-space-change |
行末の空白と、その他の1文字以上の空白の連続の量の違いを無視します。空白なしと空白ありは区別します。 |
-i, --ignore-case |
大文字と小文字の差異を無視します。 |
--color=auto |
サポートされているGNUバージョンで端末出力に色を付けます。 |
実践的活用例
パッチファイルを作成する
実在する original.conf と modified.conf を用意し、差分を未使用の出力名へ保存します。差分があれば終了状態1でもパッチは保存されますが、状態2などのエラー時には完全な出力と判断しないでください。適用する側の作業場所で解釈できる相対パスを使い、まず保存内容を確認します。
diff -u original.conf modified.conf > config.patch
ディレクトリの変更を要約する
ファイルの内容全体が必要ない場合は、-qrで内容が異なるファイルと片方にしかないパスを要約します。
diff -qr release-a release-b
空白の違いを除いて確認する
空白に意味がない場合にのみ使用します。Pythonのようにインデントが意味を持つ言語では、結果を慎重に解釈します。
diff -u -b before.txt after.txt
diffと関連するコマンドの比較
| コマンド | 主な役割 | 適した状況 |
|---|---|---|
diff |
行単位のテキストの違い | 設定・ソース・ディレクトリの比較 |
cmp |
バイト単位での最初の違い | 同一かどうかとオフセットの確認 |
git diff |
リポジトリ変更の比較 | Git作業ツリーとコミット |
comm |
ソートされた二つのファイルの集合の比較 | 共通・固有行の分離 |
使用する際の注意点
終了ステータス1は差異があることを意味します
スクリプト内で単純なエラーとして処理すると、正常な比較結果を失敗と誤解することがあります。
バイナリファイルには詳細な行比較は適していません
バイト単位の同一性はcmpコマンドによる比較やチェックサムで確認できます。通常の diff はバイナリの詳細な行比較には向きません。
空白の無視は実際の違いを隠すことがある
形式やインデントが意味を持つファイルには、無視オプションを安易に適用しません。
FAQ
diff の出力がない場合は何を意味しますか?
比較が正常終了し、終了状態が0であれば、選んだ比較条件で報告すべき差分がないことを示します。空白無視などの指定やエラー診断も確認してください。
最も読みやすい出力形式は何ですか?
一般的には、diff -u の unified 形式が文脈と共に表示され、読みやすいです。
ディレクトリ全体も比較できますか?
-rでサブディレクトリを再帰的に比較できます。
diffが終了コード1を返した場合、それはエラーですか?
いいえ。通常は差異が見つかったことを示す正常な結果で、GNU版の比較エラーは通常2です。シグナルなどによる異常終了は別途確認します。




