Ubuntuで2つのファイルの内容を比較する「cmp」コマンドについて説明をします。
「cmp」コマンドの使い方
「cmp」コマンドは、2つのファイルをバイト単位で比較し、ファイル内容について差異の有無を確認するコマンドです。
ファイルの比較において、「cmp」コマンドは内容が異なる箇所を検出すると、その最初の差異箇所を表示して処理を終了します。
なお、ファイル名やタイムスタンプは比較の対象となりません。
使い方は簡単で、下記のように比較したいファイルを指定するだけです。
cmp ファイル1 ファイル2
これで、ファイル1とファイル2が比較され、差異が見つかった場合は最初の差異箇所が表示されます。
ファイルが一致していれば、何も出力されません。
実行例
ファイルの内容が一致している「Hello_01.txt」と「Hello_02.txt」で比較を行ってみます。
ファイルの内容が同じなので、下記のよう何も表示されません。
$ cmp Hello_01.txt Hello_02.txt
ファイルの内容が異なる「Hello_01.txt」と「Hello_03.txt」で比較を行ってみます。
中身が異なる場合は、下記のように最初に差異があった場所を表示してくれます。
$ cmp Hello_01.txt Hello_03.txt Hello_01.txt Hello_03.txt differ: char 31, line 2
ちなみに、「Hello_01.txt」と「Hello_03.txt」の中身は以下のようになっています。
$ cat Hello_01.txt Hello World. This is test text. $ cat Hello_03.txt Hello World. This is test text!! cmp commnad test.
オプション
普段使用しそうな下記のオプションについて説明をします。
- -l 異なる部分毎にバイト番号を10進数、異なる部分のバイトを8進数で表示
- -s 終了値のみを返します
-l オプション
「-l」オプションを使用すると、比較したファイルに異なる部分毎に、バイト番号と異なる内容を8進数で表示してくれます。
比較するファイルのサイズが大きくて異なる部分が多い場合は、大量に差異部分が表示されるので注意してください。
cmp -l ファイル1 ファイル2
実際に「-l」オプションを使用して「Hello_01.txt」と「Hello_03.txt」ファイルを比較をしてみます。
$ cmp -l Hello_01.txt Hello_03.txt 31 56 41 32 12 41 cmp: EOF on Hello_01.txt after byte 32
比較結果をみると「31」と「32」バイト目が異なっていることがわかります。
31バイト目での差異は、8進数表記で「56」と「41」なので、わかりやすく「echo」コマンドを使って8進数をASCIIテキストに変換してみると、下記のように「.」と「!」という違いであることがわかりました。
$ echo -e "\0056" . $ echo -e "\0041" !
比較したファイルの内容はそれぞれ下記の通りです。
$ cat Hello_01.txt Hello World. This is test text. $ cat Hello_03.txt Hello World. This is test text!! cmp commnad test.
-s オプション
「-s」オプションを使用すると、比較結果の終了値だけを返してきます。
返ってくる終了値は下記の通りです。
- 0 同じ
- 1 異なる
- 2 アクセス不可
終了値は「$?」で表示することができるので、それぞれのケースで表示させてみます。
内容が同じファイルを比較した場合は、終了値として「0」が帰ってきます。
$ cmp -s Hello_01.txt Hello_02.txt $ echo $? 0
内容が異なるファイルを比較した場合は、終了値として「1」が帰ってきます。
$ cmp -s Hello_01.txt Hello_03.txt $ echo $? 1
比較対象のファイルが読み取れない・アクセスできない場合は終了値として「2」が帰ってきます。
$ ls -l Hello_04.txt -rw------- 1 root root 32 Feb 14 18:54 Hello_04.txt $ cmp -s Hello_01.txt Hello_04.txt $ echo $? 2
シェルスクリプトとして使ってみる
「cmp -s」を使うとシェルスクリプトでファイルの比較を行って、比較結果で異なる処理を行うことが簡単にできます。
以下のシェルスクリプトは、「cmp -s」コマンドでファイルを比較して内容が同じかどうかの確認を行い、その結果に応じて、同じ場合は特定の処理を行い異なる場合は別の処理を行うというシェルスクリプトになります。
下記のシェルスクリプトでは、比較したファイルの内容が同じ場合は「OK」と表示し、それ以外は「NG」と表示させています。
#!/bin/bash
FILE_1="Hello_01.txt"
FILE_2="Hello_02.txt"
cmp -s "$FILE_1" "$FILE_2"
if [ $? -eq 0 ]; then
echo "OK"
else
echo "NG"
fi
exit 0
このシェルスクリプトは「file_check_if.sh」という名前で作成してあって、「FILE_1」と「FILE_2」に設定してあるファイルの内容が同じ場合は下記のとおり「OK」と表示します。
$ bash ./file_check_if.sh OK
ファイルの内容が異なる場合や、ファイルが読み込めなかった場合など、返り値が「0」以外だった場合は「NG」と表示します。
$ bash ./file_check_if.sh NG
圧縮されたファイルには「zcmp」コマンド
「zcmp」コマンドを使用すると、「gzip」で圧縮されたファイルの比較をすることが出来ます。
zcmp ファイル1 ファイル2
圧縮を行っていない下記ファイルを、「cmp」で比較を行ってみます。
- Hello_01.txt
- Hello_02.txt
- Hello_03.txt
「Hello_01.txt」と「Hello_02.txt」は同じ内容のファイルで、「Hello_03.txt」だけが内容が異なるファイルであることがわかります。
$ cmp Hello_01.txt Hello_02.txt $ cmp Hello_01.txt Hello_03.txt Hello_01.txt Hello_03.txt differ: char 31, line 2
「gzip」でファイルを圧縮してから「cmp」で比較を行ってみます。
$ gzip -k Hello_01.txt $ gzip -k Hello_02.txt $ gzip -k Hello_03.txt
「Hello_01.txt」と「Hello_02.txt」の内容は同じなのに、圧縮後のデータで比較を行っているため内容が異なるデータと判断されてしまっています。
$ cmp Hello_01.txt.gz Hello_02.txt.gz Hello_01.txt.gz Hello_02.txt.gz differ: char 18, line 1
「zcmp」コマンドを使用してファイルの比較を行うと、圧縮前の内容を比較してくれるため、ファイルの内容に差異が無いという結果になります。
$ zcmp Hello_01.txt.gz Hello_02.txt.gz
ファイルに差異があった場合も、圧縮前のファイルを比較した場合と同じ場所を差異があった場所として表示してくれています。
$ zcmp Hello_01.txt.gz Hello_03.txt.gz /dev/fd/5 - differ: char 31, line 2
「cmp」と「zcmp」で「-l」オプションを指定して比較を行った結果を比べてみると、どちらも異なる場所と内容が同じであると表示されています。
$ cmp -l Hello_01.txt Hello_03.txt 31 56 41 32 12 41 cmp: EOF on Hello_01.txt after byte 32 $ zcmp -l Hello_01.txt.gz Hello_03.txt.gz 31 56 41 32 12 41 cmp: EOF on /dev/fd/5 after byte 32
このことから、「zcmp」は圧縮されたファイルの内容を読み取って、ファイルの比較を行っていることがわかります。
コメント