diff コマンド
目次
概要
diff - ファイルの内容を比較するコマンドライン
diff [OPTION]... FILES
対象バージョン
- RHEL 10 : GNU diffutils 3.10
- Ubuntu 24.04 : GNU diffutils 3.10
説明
ファイル比較
diff コマンドは二つのファイルを比較してその差分を表示します。下記は、fileA.txt と fileB.txt を比較して、2行目が orange から melon に変更されていることを示しています。
$ diff fileA.txt fileB.txt 2c2 < orange --- > melon
ディレクトリ比較
ディレクトリごと比較することもできます。下記は、./srcA ディレクトリと ./srcB ディレクトリ配下のすべてのファイルに対して再帰的に比較を行います。
$ diff -r ./srcA ./srcB
ディレクトリ比較では -x オプションで比較対象から除外するディレクトリやファイルを指定することができます。下記の例では old という名前のディレクトリや *.log にマッチするファイルを比較対象から除外しています。
$ diff -r -x old -x "*.log" ./srcA ./srcB
パッチファイル
例えば、本番用のソースコードに対して評価環境では少し修正を加える必要がある場合、その修正の差分情報をパッチファイルとして保存しておき、本番用ソースコードがバージョンアップしてもパッチを適用することで、同じ修正を自動的に適用することができます。この目的のためには、patch コマンドと diff コマンドの -u (または -c) オプションを使用します。
# 変更前ファイルと変更後ファイルの差分をパッチファイルに記録する $ diff -u example.py example_test.py > example.patch # 変更前ファイルに対して、上記のパッチを適用する $ patch example.py < example.patch
この作業をディレクトリ単位で行うこともできます。この場合、patch コマンドに -d オプションを指定します。
# 変更前ディレクトリと変更後ディレクトリの差分をパッチファイルに記録する $ diff -u ./src ./src_test > src.patch # 変更前ディレクトリに対して、上記のパッチを適用する $ patch -d ./src < src.patch
左右二分割比較
-y オプションを使用すると、画面を左右に二分割し、左側に変更前、右側に変更後のファイルを表示することができます。境界線部に 追加(>)、削除(<)、変更(|)のマークが表示されます。
$ diff -W 80 -y fileA.py fileB.py
from datetime import datetime from datetime import datetime
def greeting(): def greeting():
> """ Print greeting message. """
now = datetime.now() now = datetime.now()
hour = now.hour hour = now.hour
if 5 <= hour < 12: if 5 <= hour < 12:
print("Good morning.") print("Good morning.")
elif 12 <= hour < 17: elif 12 <= hour < 17:
print("Good afternoon.") print("Good afternoon.")
elif 17 <= hour < 21: | elif 17 <= hour < 22:
print("Good evening.") print("Good evening.")
else: else:
print("Good night.") print("Good night.")
if __name__ == "__main__": if __name__ == "__main__":
greeting() greeting()
<
オプション
ディレクトリ比較
- -r, --recursive
- 指定したディレクトリ配下のすべてのファイルに対して比較を行います。
$ diff -r ./srcA ./srcB
- --ignore-file-name-case
-rオプション指定時、ファイル名の大文字・小文字を無視します。- --no-ignore-file-name-case
-rオプション指定時、ファイル名の大文字・小文字を無視しません(デフォルト)。- -N, --new-file
-rオプション指定時、片方に存在しないファイルがあれば空ファイルが存在すると見なして比較します。- --unidirectional-new-file
-rオプション指定時、比較元ディレクトリに存在しないファイルがあれば空ファイルが存在すると見なして比較します。- -S, --starting-file=FILE
-rオプション指定時、FILEで指定したファイルが見つかるまで比較をスキップします。巨大なディレクトリの比較を途中から再開したい時に便利です。前回どこまで比較したかは-sオプションをつけていれば知ることができます。$ diff -r -S README.md ./srcA ./srcB
比較対象からの除外
- -x, --exclude=PAT
PATにマッチするファイルやディレクトリを比較対象から除外します。複数指定できます。下記ではoldディレクトリや、*.logファイルを比較対象から除外しています。$ diff -r -x old -x "*.log" ./srcA ./srcB
- -X, --exclude-from=FILE
FILEの各行に記載されたパターンにマッチするファイルやディレクトリを比較対象から除外します。$ cat exclude.txt old *.log $ diff -r -X exclude.txt ./srcA ./srcB
比較ルール
- -i, --ignore-case
- 比較の際、大文字と小文字の差異を無視します。
- -E, --ignore-tab-expansion
- 比較の際、タブ文字をスペースに変換することによる差異を無視します。
- -Z, --ignore-trailing-space
- 比較の際、行末のスペースの有無を無視します。
- -b, --ignore-space-change
- 比較の際、ホワイトスペースの個数による差異を無視します。たとえば空白1個の
"Hello World"と空白2個の"Hello World"を等しいと見なします。 - -w, --ignore-all-space
- 比較の際、すべてのホワイトスペースを無視します。たとえば空白1個の
"Hello World"と空白0個の"HelloWorld"も等しいと見なします。 - -B, --ignore-blank-lines
- 比較の際、空行の有無による差異を無視します。
- --strip-trailing-cr
- 比較の際、キャリッジリターン(CR)文字を無視します。Windows のファイル(CR LF)と Linux のファイル(LF)を比較する際に便利です。
- -I, --ignore-matching-lines=RE
- 比較の際、正規表現
REにマッチする行を無視します。 - -a, --text
- バイナリファイルと思われるファイルでもテキストとみなして比較します。
出力フォーマット
- --normal
- ノーマル形式で出力します(デフォルト)。
$ diff fileA.txt fileB.txt 2c2 < orange --- > melon
- -c, -C NUM, --context[=NUM]
- コンテキスト形式で出力します。
NUMは前後何行表示するかを指定します。!は異なっている行を示します。コンテキスト形式の出力はpatchコマンドの入力とすることができます。$ diff -c fileA.txt fileB.txt *** fileA.txt 2025-07-29 18:30:19.837971903 +0900 --- fileB.txt 2025-07-29 18:30:32.261970806 +0900 *************** *** 1,3 **** apple ! orange banana --- 1,3 ---- apple ! melon banana
- -u, -U NUM, --unified[=NUM]
- ユニファイド形式で出力します。
NUMは前後何行表示するかを指定します。+は追加行、-は削除行を示します。ユニファイド形式の出力はpatchコマンドの入力とすることができます。--- fileA.txt 2025-07-29 18:30:19.837971903 +0900 +++ fileB.txt 2025-07-29 18:30:32.261970806 +0900 @@ -1,3 +1,3 @@ apple -orange +melon banana
- -q, --brief
- ブリーフ形式で出力します。ファイルが異なっている旨のみが出力されます。
$ diff -q ./srcA ./srcB Files ./srcA/fileA.txt and ./srcB/fileA.txt differ
- -s, --report-identical-files
- 通常の出力に加え、同じ内容だったファイルに関する情報を出力します。
$ diff -rs ./srcA ./srcB diff -rs ./srcA/fileA.txt ./srcB/fileA.txt 2c2 < orange --- > melon Files ./srcA/fileB.txt and ./srcB/fileB.txt are identical
左右二分割形式
- -y, --side-by-side
- 比較元と比較先を左右に表示する左右二分割形式で出力します。
$ diff -y fileA.txt fileB.txt apple apple orange | melon banana banana
- --left-column
-yオプション使用時、同じ行は左カラムのみ出力します。$ diff -y --left-column fileA.txt fileB.txt apple ( orange | melon banana (
- --suppress-common-lines
-yオプション使用時、異なる行のみ出力します。$ diff -y --suppress-common-lines fileA.txt fileB.txt orange | melon
- -W, --width=NUM
-yオプションの1行の最大幅を指定します。デフォルトは-w 130です。$ $ diff -y -W 22 fileA.txt fileB.txt apple apple orange | melon banana banana
ファイル名・関数名
- -p, --show-c-function
-cや-uオプション指定時、ファイルをC言語のプログラムとして解析し、異なっている箇所が含まれる関数名を表示します。-pのみを指定すると-cpと見なします。$ diff -up fileA.c fileB.c --- fileA.c 2025-07-29 22:13:03.001952386 +0900 +++ fileB.c 2025-07-29 22:13:18.489953203 +0900 @@ -13,7 +13,7 @@ struct ISSUE **get_issues(char *project) issues = get_method( "issues", project, - "journals", + "journals,relations", offset, limit );- -F, --show-function-line=RE
-cや-uオプション指定時、正規表現REにマッチした行を表示します。Python などの関数名を表示するのに便利です。$ diff -u -F '^\s*def ' fileA.py fileB.py --- fileA.py 2025-07-29 20:21:12.877955067 +0900 +++ fileB.py 2025-07-29 20:21:22.677955064 +0900 @@ -18,7 +18,7 @@ def get_issues(project): params = { "project": project, - "include": "journals", + "include": "journals,relations", "offset": offset, "limit": limit, }- --label LABEL
-c,-uオプション指定時、ファイル名とタイムスタンプの代わりにラベルを表示します。2つ指定することができ、1つ目は旧ファイル、2つ目は新ファイルのラベルとなります。$ diff -u --label "OLD_FILE" --label "NEW_FILE" fileA.py fileB.py --- OLD_FILE +++ NEW_FILE @@ -18,7 +18,7 @@ params = { "project": project, - "include": "journals", + "include": "journals,relations", "offset": offset, "limit": limit, }
シンボリックリンク
- --no-dereference
- シンボリックリンク先を参照しません。
タブ文字
- -t, --expand-tabs
- 異なる行を表示する際に、タブ文字をスペースに変換して表示します。比較ロジックには影響しません。
-yオプション指定時にタブ位置がずれてしまうのを綺麗に表示する際などに便利です。 - -T, --initial-tab
-c,-uオプション指定時、差異のある行表示の前にスペースの代わりにタブ文字を表示します。行頭の!などの数文字によって行表示のタブ位置がずれてしまうのを防ぐのに便利です。- --suppress-blank-empty
- 空の出力行の前にスペースやタブ文字を出力しません。(※効能はよくわかりませんでした。)
- --tabsize=NUM
- タブストップ位置を
NUMカラム毎とします。デフォルトは 8 です。
カラー表示
- --color[=WHEN]
- 出力のカラー化について指定します。
WHENには下記のいずれかを指定します。always: 常にカラー表示します。never: 常にカラー表示しません。auto: 出力端末によってカラー/非カラーを自動判別します(デフォルト)。
- --palette=PALETTE
- カラーモードの色を指定します。
adは追加行、deは削除行、lnは行番号を意味します。色は ANSI カラーコードで指定します。$ diff --color --palette="ad=32:de=35:ln=3;35;43" fileA.txt fileB.txt
カスタマイズドフォーマット
- --line-format=LFMT
- 各行のフォーマットを指定します。
LFMTの詳細は--LTYPE-line-formatを参照してください。 - --LTYPE-line-format=LFMT
- 追加行、削除行、無変更行各行のフォーマットを指定します。
LTYPEには下記のいずれかを指定します。new: 追加された行old: 削除された行unchanged: 変更されなかった行
LFMTには通常の文字列の他、下記を指定できます。fmtには04dのようなprintf()で指定するフォーマットを指定します。%L: 行の内容%l: 行の内容(行末の改行を除去したもの)%fmtn: 行番号%%: パーセント(%)%c'C': 文字 C%c'\oct': 8進数の文字コード
$ diff \ --new-line-format="I %3dn: %L" \ --old-line-format="D %3dn: %L" \ --unchanged-line-format=" %3dn: %L" \ fileA.txt fileB.txt 1: Unchanged line content 2: Unchanged line content : I 7: Inserted line content : D 17: Old line content I 17: New line content : D 22: Deleted line content : - --GTYPE-group-format=GFMT
- 連続する追加行、削除行、変更行、無変更行をブロックとして、ブロックの出力フォーマットを細かく指定します。
GTYPEには下記のいずれかを指定します。new: 追加された行old: 削除された行changed: 変更された行unchanged: 変更されなかった行
GFMTには通常の文字列の他、下記を指定できます。fmtには04dのようなprintf()で指定するフォーマットを指定します。%<: 比較元ファイルの行%>: 比較先ファイルの行%=: 共通の行%fmtF: グループの最初の行番号%fmtL: グループの最後の行番号%fmtN: グループの行数(L-F+1)%fmtE: F - 1%fmtM: L - 1%%: パーセント(%)%c'C': 文字 C%c'\oct': 8進数の文字コード%(A=B?T:E): A=B であれば T、さもなくば E
$ diff \ --old-group-format="--- Delete(%dF) ---%c'\012'%<" \ --new-group-format="--- Insert(%dF) ---%c'\012'%>" \ --changed-group-format="--- Change(%dF) ---%c'\012'%=" \ --unchanged-group-format="" \ fileA.txt fileB.txt --- Insert(7) --- Inserted lines... --- Change(17) --- Changed lines... Changed lines... --- Delete(22) --- Deleted lines...
他コマンド連携
- -e, --ed
edコマンドのスクリプト形式で出力します。下記の例ではfileA.txtとfileB.txtの差分をpatch.edファイルに記録し、最後にfileC.txtに書き出すスクリプトを追加し、edコマンドに渡しています。これにより、fileA.txtからfileB.txtと同じ内容のfileC.txtを作成することができます。現在では-cまたは-u形式の出力をpatchコマンドに入力するのが一般的です。$ diff -e fileA.txt fileB.txt > patch.ed $ echo "w fileC.txt" >> patch.ed $ ed fileA.txt < patch.ed
- -n, --rcs
- バージョン管理ツール RCS が使用する形式で出力します。
$ diff -n fileA.txt fileB.txt d2 1 a2 1 melon
- -D, --ifdef=NAME
- C言語プリプロセッサが処理する形式で出力します。比較元ファイルと比較先ファイルを C言語の
#ifdef文で切り替えられるようにマージします。$ diff -D VERSION_123 fileA.c fileB.c : #ifndef VERSION_123 "journals", #else /* VERSION_123 */ "journals,relations", #endif /* VERSION_123 */ : - -l, --paginate
- 出力を
prコマンドに渡して印刷時のヘッダ情報(ページ番号など)を付与します。$ diff -l fileA.txt fileB.txt 2025-07-29 21:56 diff -l fileA.txt fileB.txt Page 1 :
1対N・N対1比較
- --from-file=FILE1
FILE1を比較元、残りの引数を比較先として比較します。下記の例ではfileA.txtとfileB.txt、fileA.txtとfileC.txtを比較します。ディレクトリを指定することもできます。$ diff --from-file=fileA.txt fileB.txt fileC.txt
- --to-file=FILE2
FILE2を比較先、残りの引数を比較元として比較します。下記の例ではfileA.txtとfileC.txt、fileB.txtとfileC.txtを比較します。 ディレクトリを指定することもできます。$ diff --to-file=fileC.txt fileA.txt fileB.txt
比較アルゴリズム
- -d, --minimal
- 結果の出力行数が少なくなるように高度な比較を行います。通常の比較より時間がかかることがあります。
- --horizon-lines=NUM
- 比較の際、分析対象とする前後の行数を指定します。この値を大きくしたり
--minimalと組み合わせることでより大域的な分析ができるようになり、読みやすい結果を得ることができるかもしれません。 - --speed-large-files
- 通常の比較ではファイル内容をすべてメモリに展開しますが、大きなファイルに対しては部分的に展開するように指示します。大域的な比較はできなくなりますが、メモリ使用量を減らすことができます。
ヘルプ表示
- --help
- ヘルプを表示して終了します。
- -v, --version
- バージョン情報を表示して終了します。
関連項目
- patch(未稿)
Copyright (C) 2025 杜甫々
初版:2025年8月3日 最終更新:2025年8月3日
https://www.tohoho-web.com/linux/cmd/diff.html