Linux の diff コマンド:ファイル比較

LinuxLinuxBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Linux を扱うソフトウェア開発者やシステム管理者にとって必須のツールである diff コマンドを探ります。diff コマンドは、2 つのファイルの内容を比較し、それらの違いを強調表示するために使用されます。このスキルは、コード バージョンを管理したり、設定ファイルの変更をレビューしたり、テキストベースのデータの不一致を特定したりする際に特に価値があります。

私たちは、ソフトウェア開発のシナリオをシミュレートします。そこでは、diff コマンドを使ってファイルの異なるバージョンを比較し、このコマンドが現実の状況でどのように適用できるかを理解する手助けをします。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/FileandDirectoryManagementGroup(["File and Directory Management"]) linux(("Linux")) -.-> linux/VersionControlandTextEditorsGroup(["Version Control and Text Editors"]) linux/FileandDirectoryManagementGroup -.-> linux/cd("Directory Changing") linux/VersionControlandTextEditorsGroup -.-> linux/diff("File Comparing") subgraph Lab Skills linux/cd -.-> lab-219189{{"Linux の diff コマンド:ファイル比較"}} linux/diff -.-> lab-219189{{"Linux の diff コマンド:ファイル比較"}} end

diff の基本的な使い方を理解する

diff コマンドの基本的な出力を理解するために、2 つの単純なテキスト ファイルを比較してみましょう。

まず、プロジェクト ディレクトリに移動します。

cd /home/labex/project

次に、diff コマンドを使って 2 つのファイルを比較します。

diff file1.txt file2.txt

次のような出力が表示されるはずです。

1,2c1,2
< This is version 1 of the file.
< It contains some initial content.
---
> This is version 2 of the file.
> It contains updated content.
4c4
< This is the fourth line.
---
> This is a modified fourth line.

この出力を分解してみましょう。

  • 数字(例:1,2c1,2)は、変更が発生する両方のファイル内の行番号を示します。
  • 文字 c は「変更」を意味します。他の可能性のある文字は、「追加」を意味する a と、「削除」を意味する d です。
  • < で始まる行は最初のファイル(file1.txt)からのものです。
  • > で始まる行は 2 番目のファイル(file2.txt)からのものです。
  • --- は、最初のファイルと 2 番目のファイルの内容を区切ります。

この出力は、次のことを示しています。

  1. 両方のファイルの 1 行目と 2 行目が異なっています。
  2. 両方のファイルの 4 行目が異なっています。
  3. 3 行目(出力に表示されていません)は両方のファイルで同じです。

Python スクリプトを比較する

次に、diff コマンドをもっと現実的なシナリオに適用してみましょう。Python スクリプトを開発しており、2 つのバージョンを比較したいとします。

まず、両方のスクリプト バージョンの内容を見てみましょう。

cat script_v1.py

次のように表示されるはずです。

def greet(name):
    print("Hello, " + name + "!")

def main():
    name = input("Enter your name: ")
    greet(name)

if __name__ == "__main__":
    main()

次に、2 番目のバージョンを見てみましょう。

cat script_v2.py

次のように表示されるはずです。

def greet(name):
    print(f"Hello, {name.capitalize()}!")

def main():
    name = input("Enter your name: ")
    greet(name)
    print("Thank you for using this script!")

if __name__ == "__main__":
    main()

次に、これらのスクリプトを比較するために diff を使います。

diff script_v1.py script_v2.py

次のような出力が表示されるはずです。

2c2
<     print("Hello, " + name + "!")
---
>     print(f"Hello, {name.capitalize()}!")
6a7
>     print("Thank you for using this script!")

この出力は、次のことを示しています。

  1. 2 行目が変更されました。挨拶文が f-string を使うようになり、名前が大文字になります。
  2. 新しい行(新しいバージョンの 7 行目)が追加され、感謝のメッセージが表示されます。

統一形式を使う

統一形式(-u オプション)は、特に大きなファイルやコンテキストが重要な場合に、より読みやすい出力を提供します。

統一形式を使って Python スクリプトを比較しましょう。

diff -u script_v1.py script_v2.py

次のような出力が表示されるはずです。

--- script_v1.py	2023-12-28 10:00:00.000000000 +0000
+++ script_v2.py	2023-12-28 10:05:00.000000000 +0000
@@ -1,8 +1,9 @@
 def greet(name):
-    print("Hello, " + name + "!")
+    print(f"Hello, {name.capitalize()}!")

 def main():
     name = input("Enter your name: ")
     greet(name)
+    print("Thank you for using this script!")

 if __name__ == "__main__":

この出力を分解してみましょう。

  • 最初の 2 行は比較対象のファイルとそのタイムスタンプを示しています。
  • - で始まる行は最初のファイル(script_v1.py)からのものです。
  • + で始まる行は 2 番目のファイル(script_v2.py)からのものです。
  • -+ がない行はコンテキストを提供し、ファイル間で変更されていません。
  • @@ -1,8 +1,9 @@ の行は、最初のファイルの 1 行目から 8 行目と、2 番目のファイルの 1 行目から 9 行目を見ていることを示しています。

この形式は、変更点の周りにより多くのコンテキストを提供するため、多くの場合好まれます。

空白の変更を無視する

時には、空白(スペース、タブ)の違いは重要ではありません。-w オプションを使うと、diff にこれらの変更を無視させることができます。

空白をいくつか変更した新しいバージョンのスクリプトを作成しましょう。

注:スクリプトに空白を手動で追加する必要があります。コードをコピーして貼り付けると、空白は含まれません。

cat > script_v3.py << EOF
def greet(name):
    print(f"Hello, {name.capitalize()}!")

def main():
    name = input("Enter your name: ")
    greet(name)
    print("Thank you for using this script!")

if __name__ == "__main__":
    main()
EOF

次に、-w オプションを使わずに、そして使ってから、script_v2.py と script_v3.py を比較しましょう。

diff script_v2.py script_v3.py

空白のためにいくつかの違いが見られるかもしれません。次に試してみてください。

diff -w script_v2.py script_v3.py

出力が表示されないはずで、空白を無視した場合には違いがないことを示しています。

これは、内容の変更に焦点を当てたい場合に便利です。

ディレクトリを比較する

diff コマンドは、また、エンティアなディレクトリを比較することもできます。いくつかのファイルを含む 2 つのディレクトリを作成して、それらを比較してみましょう。

ディレクトリとファイルを作成します。

echo "This is a file in dir1" > dir1/file.txt
echo "This is a file in dir2" > dir2/file.txt
echo "This file is unique to dir1" > dir1/unique1.txt
echo "This file is unique to dir2" > dir2/unique2.txt

次に、ディレクトリを比較します。

diff -r dir1 dir2

次のような出力が表示されるはずです。

Only in dir1: unique1.txt
Only in dir2: unique2.txt
diff -r dir1/file.txt dir2/file.txt
1c1
< This is a file in dir1
---
> This is a file in dir2

この出力は、次のことを示しています。

  1. dir1 には dir2 に存在しない unique1.txt という名前のファイルがあります。
  2. dir2 には dir1 に存在しない unique2.txt という名前のファイルがあります。
  3. file.txt は両方のディレクトリに存在しますが、内容が異なります。

-r オプションにより、diff は再帰的にサブディレクトリも比較します。これは、複雑なディレクトリ構造を比較する際に便利です。

まとめ

この実験では、ソフトウェア開発のコンテキストで Linux の diff コマンドを調べました。以下のことが学べました。

  1. 2 つのテキスト ファイルを比較し、基本的な diff 出力を解釈する方法
  2. Python スクリプトの異なるバージョンを比較する方法
  3. より読みやすい出力のために統一形式を使用する方法
  4. 比較時に空白の変更を無視する方法
  5. 再帰的にエンティアなディレクトリを比較する方法

この実験では扱わなかった追加の diff オプションには、以下があります。

  • -y:並列比較
  • -i:大文字小文字の違いを無視する
  • -b:空白の量の変更を無視する
  • -B:行全体が空白の変更を無視する
  • -q:ファイルが異なる場合のみ報告し、違いを表示しない

これらのオプションを組み合わせることで、より特定の比較を行うことができます。