Bashシェルスクリプトで2つのディレクトリ内のファイル名のみを比較する(ファイルの内容の違いは許容)

Bash,CentOS,Linux,Ubuntu

はじめに

過去に以下のようなエントリを投稿しました。

今回は似ていますが、
存在するファイル名の違いを出力してみたいと思います。

ファイルの中身に違いがあっても差分として検出しません。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ head -n 2 /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

検証のための事前準備

比較するための2つのディレクトリ dir1dir2 を作成し、いくつかのファイルを作成しておきます。

後ほどこの2つのディレクトリに含まれているファイル名を比較します。

# dir1 とそのサブディレクトリ、含まれるファイルを作成
mkdir -p dir1/a dir1/b dir1/c/d
date >dir1/a/1.txt
date >dir1/b/2.txt
date >dir1/c/3.txt
date >dir1/c/4.txt
date >dir1/c/d/5.txt

# dir2 とそのサブディレクトリ、含まれるファイルを作成
mkdir -p dir2/a dir2/b dir2/c/d
date >dir2/a/1.txt
date >dir2/c/3.txt
date >dir2/c/5.txt
date >dir2/c/d/5.txt

tree コマンドでそれぞれのディレクトリの階層構造を確認してみましょう。

# dir1 の階層構造を確認
$ tree dir1
dir1
|-- a
|   `-- 1.txt
|-- b
|   `-- 2.txt
`-- c
    |-- 3.txt
    |-- 4.txt
    `-- d
        `-- 5.txt

4 directories, 5 files

# dir2 の階層構造を確認
$ tree dir2
dir2
|-- a
|   `-- 1.txt
|-- b
`-- c
    |-- 3.txt
    |-- 5.txt
    `-- d
        `-- 5.txt

4 directories, 4 files

2つのディレクトリに含まれているファイル名の違いを出力

すべてのファイルの内容も含めて2つのディレクトリを比較するときには、以下のエントリで取り上げたように diff -r dir1 dir2 で確認できます。

ただし今回は「ファイル名」のみの違いを確認したいので、少し異なった方法取ります。

# dir1 と dir2 の中のファイルの名前を比較
$ diff <(cd dir1; find . -type f | sort) <(cd dir2; find . -type f| sort)
2d1
< ./b/2.txt
4c3
< ./c/4.txt
---
> ./c/5.txt

dir1 には b/2.txtc/4.txt
dir2 には c/5.txt があります。
それぞれのファイルが差異として検出されました。

dir1 と全く同じディレクトリの場合はどうなるでしょう?

# dir1 をコピーして、全く同じ階層の dir3 を作成
$ cp -a dir1 dir3

# 比較してみる
$ diff <(cd dir1; find . -type f | sort) <(cd dir3; find . -type f| sort)

# 何も出力されない

何も出力されません。差異がなかったということです。

2つのディレクトリに含まれているファイル名に違いがあるかを判定

差異があるかどうかを判定したい(具体的なファイル名は必要ない)場合は、 cmp コマンドが利用できます。

# cmp を実行し、実行後ステータスを確認してみる
$ cmp -s <(cd dir1; find . -type f | sort) <(cd dir2; find . -type f| sort)

$ echo $?
1

# 実行結果を利用して分岐処理を行う
$ cmp -s <(cd dir1; find . -type f | sort) <(cd dir2; find . -type f| sort) && echo "差異なし" || echo "差異あり"
差異あり

dir1 と全く同じディレクトリの場合はどうなるでしょう?

# dir1 をコピーして、全く同じ階層の dir3 を作成
$ cp -a dir1 dir3

$ cmp -s <(cd dir1; find . -type f | sort) <(cd dir3; find . -type f| sort) && echo "差異なし" || echo "差異あり"
差異なし

ひとこと

2つのディレクトリの中の「ファイル名」だけを比較するというケースはあまりしたことがありませんが、バイナリデータを含むファイルの比較などで便利そうですね。

Bash,CentOS,Linux,Ubuntu