ソート済みファイル同士を比較したい
2つのソート済みファイルを比較して、どちらか片方にだけ存在する行や、両方に共通する行を抽出したい。
例えば以下のような2つのファイルがある。
apple
banana
cherry
grape
banana
cherry
melon
orange
2つのファイルを比較して、以下の情報を得たい。
- file1にだけある行: apple, grape
- file2にだけある行: melon, orange
- 両方に共通する行: banana, cherry
comm コマンド
commコマンドは2つのソート済みファイルを行単位で比較するコマンド。
$ comm file1.txt file2.txt
apple
banana
cherry
grape
melon
orange
commコマンドは3列で出力する。
- 1列目(インデントなし): file1にだけある行
- 2列目(タブ1つ): file2にだけある行
- 3列目(タブ2つ): 両方に共通する行
上記の出力では、appleとgrapeが1列目、melonとorangeが2列目、bananaとcherryが3列目に表示される。
file1にだけある行を表示する
-2と-3オプションで2列目と3列目を非表示にすると、file1にだけある行を抽出できる。
$ comm -23 file1.txt file2.txt
apple
grape
file1にだけ存在する行が出力される。
file2にだけある行を表示する
-1と-3オプションで1列目と3列目を非表示にすると、file2にだけある行を抽出できる。
$ comm -13 file1.txt file2.txt
melon
orange
file2にだけ存在する行が出力される。
両方に共通する行を表示する
-1と-2オプションで1列目と2列目を非表示にすると、両方に共通する行を抽出できる。
$ comm -12 file1.txt file2.txt
banana
cherry
両方のファイルに共通する行が出力される。
ファイルは事前にソートが必要
commコマンドはソート済みファイルを前提とする。ソートされていないファイルを指定すると正しい結果が得られない。
cherry
apple
banana
banana
orange
cherry
$ comm -12 unsorted1.txt unsorted2.txt
comm: file 1 is not in sorted order
comm: file 2 is not in sorted order
comm: input is not in sorted order
ソートされていないため、エラーメッセージが表示される。
事前にsortコマンドでソートするか、プロセス置換を使用する。
$ comm -12 <(sort unsorted1.txt) <(sort unsorted2.txt)
banana
cherry
プロセス置換<(command)を使用すると、コマンドの出力を一時ファイルとして扱える。
具体例
2つのユーザーリストの差分を確認する
サーバー間でユーザーリストの差分を確認する場合にcommコマンドが便利。
$ cut -d: -f1 /etc/passwd | sort > users1.txt
$ ssh server2 "cut -d: -f1 /etc/passwd" | sort > users2.txt
$ comm -3 users1.txt users2.txt
-3オプションで共通部分を非表示にすると、どちらかのサーバーにしか存在しないユーザーを確認できる。
今日追加されたファイルを確認する
昨日のファイルリストと今日のファイルリストを比較して、新しく追加されたファイルを確認する。
$ ls /var/www/html | sort > yesterday.txt
# (1日後)
$ ls /var/www/html | sort > today.txt
$ comm -13 yesterday.txt today.txt
-13オプションでtoday.txtにだけ存在する行(今日追加されたファイル)を抽出できる。
パッケージの差分を確認する
2つのサーバーで異なるパッケージがインストールされているか確認する。
$ rpm -qa | sort > server1_packages.txt
$ ssh server2 "rpm -qa | sort" > server2_packages.txt
$ comm -3 server1_packages.txt server2_packages.txt
サーバー間のパッケージの差分を確認できる。
git管理対象のファイルと実際のファイルを比較する
gitで管理されているファイルと、実際のディレクトリ内のファイルを比較する。
$ git ls-files | sort > git_files.txt
$ find . -type f | sed 's|^\./||' | sort > actual_files.txt
$ comm -13 git_files.txt actual_files.txt
実際のディレクトリに存在するが、gitで管理されていないファイルを抽出できる。
