diff コマンド

目次

概要

diff - ファイルの内容を比較する

コマンドライン

diff [OPTION]... FILES

対象バージョン

説明

ファイル比較

diff コマンドは二つのファイルを比較してその差分を表示します。下記は、fileA.txtfileB.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.txtfileB.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.txtfileB.txtfileA.txtfileC.txt を比較します。ディレクトリを指定することもできます。
$ diff --from-file=fileA.txt fileB.txt fileC.txt
--to-file=FILE2
FILE2 を比較先、残りの引数を比較元として比較します。下記の例では fileA.txtfileC.txtfileB.txtfileC.txt を比較します。 ディレクトリを指定することもできます。
$ diff --to-file=fileC.txt fileA.txt fileB.txt

比較アルゴリズム

-d, --minimal
結果の出力行数が少なくなるように高度な比較を行います。通常の比較より時間がかかることがあります。
--horizon-lines=NUM
比較の際、分析対象とする前後の行数を指定します。この値を大きくしたり --minimal と組み合わせることでより大域的な分析ができるようになり、読みやすい結果を得ることができるかもしれません。
--speed-large-files
通常の比較ではファイル内容をすべてメモリに展開しますが、大きなファイルに対しては部分的に展開するように指示します。大域的な比較はできなくなりますが、メモリ使用量を減らすことができます。

ヘルプ表示

--help
ヘルプを表示して終了します。
-v, --version
バージョン情報を表示して終了します。