ことの経緯
とある業務において、MW上にxmlを用いて設定値をインポートしていた。
MW上で設定値変更も可能で、修正依頼が来るたびに修正したxmlをMWに設定しなければならない。そのため、MWの設定値とこちらで管理しているxmlとの間でずれが生じてしまう場合がたまにあった。
そこで、現在のMWに設定されている値と、こちらで管理しているxmlの値に相違がないかを把握しておきたかった。MWの設定値はxmlファイルとしてexport可能なため、お互いのxmlを比較して違いを発見するスクリプトを作成したい。
差分比較スクリプト
compared_xml.sh
# 二つのディレクトリ内にある同名のxmlファイルを比較して差分を表示する
# 一方にのみ存在するファイルまたはxml以外のファイルは比較対象外とする
# -------------------------------------------
# 事前にディレクトリの作成が必要(MASTER_DIR、DIR1、DIR2)
readonly MASTER_DIR=/tmp/compare_xml2
# 各ディレクトリ以下にxmlを配置する
readonly DIR1="${MASTER_DIR}/org/"
readonly DIR2="${MASTER_DIR}/new/"
timestamp=$(date +"%Y%m%d_%H%M%S")
readonly DIFF_LOG="${MASTER_DIR}/diff_files_${timestamp}.log"
file_sum=0
diff_files=()
# DIR1に存在しないファイル一覧
not_exist_dir1=()
# DIR2に存在しないファイル一覧
not_exist_dir2=()
# -------------------------------------------
# ログにのみ出力
function logger() {
echo "$1" >> $DIFF_LOG
}
# 画面とログ両方に出力
function func_tee() {
echo "$1" | tee -a $DIFF_LOG
}
# 引数で受け取った配列を画面とログに出力
function print_and_log_array() {
num_count=0
declare -n files=$1
if [ ${#files[@]} -eq 0 ]; then
func_tee "特になし"
else
for file in "${files[@]}"
do
num_count=`expr $num_count + 1`
func_tee "$num_count.$file"
done
fi
}
# -------------------------------------------
if [ ! -d "$DIR1" ] || [ ! -d "$DIR2" ]; then
echo "どちらかのディレクトリが存在しません。"
exit 1
fi
# DIR1とDIR2内にあるxmlファイルの重複を排除したファイル一覧
xml_files=$(( ls "$DIR1"/*.xml 2>/dev/null; ls "$DIR2"/*.xml 2>/dev/null ) | rev | cut -d"/" -f1 | rev | sort -u)
for xml_file in $xml_files; do
# 二つのディレクトリのフルバス
file_path1="$DIR1/$xml_file"
file_path2="$DIR2/$xml_file"
# 両ディレクトリに存在する
if [[ -f "$file_path1" && -f "$file_path2" ]]; then
if ! diff -q "$file_path1" "$file_path2" > /dev/null; then
logger " ============== ファイル名:$xml_file =============="
logger "diff $file_path1 $file_path2"
diff_output=$(diff --suppress-common-lines "$file_path1" "$file_path2")
logger "$diff_output"
logger ""
logger "----------------------------------------------------"
logger ""
# 差分ありのファイルを配列に追加
diff_files+=("$xml_file")
fi
file_sum=`expr $file_sum + 1`
# DIR2に存在しないファイル
elif [[ -f "$file_path1" ]]; then
not_exist_dir2+=("$xml_file")
# DIR1に存在しないファイル
elif [[ -f "$file_path2" ]]; then
not_exist_dir1+=("$xml_file")
fi
done
func_tee ""
func_tee " ============== 差分ありファイル一覧 =============="
func_tee ""
print_and_log_array diff_files
func_tee ""
func_tee "差分ファイル総数: ${#diff_files[@]}"
func_tee "比較ファイル総数: ${file_sum} (一方にのみ存在するファイルは含めず)"
func_tee ""
func_tee " ==============「${DIR2}」にのみ存在するファイル =============="
print_and_log_array not_exist_dir1
func_tee ""
func_tee " ==============「${DIR1}」にのみ存在するファイル =============="
print_and_log_array not_exist_dir2
func_tee ""
exit 0
終わりに
ターミナルとログどちらにも出力したかったので上記の実装にした。
このスクリプトで分かるのは同名ファイルの中身に違いがあるかどうか
2000ファイル近くの設定(xmlファイル)があるためスクリプト化したかった。
awkを使いこなせたらもっと端的に記述できたと思う。