方法1:知っていることを使用する
1つのファイルをループする方法を既に知っているので、ファイルを結合して、結合したファイルを処理できます。このコマンドpaste
は、2つのファイルを行ごとに結合します。2つのファイルからの行の間にタブを配置するため、このソリューションでは、ファイル名にタブがないことを前提としています。(区切り文字は変更できますが、ファイル名に存在しない文字を見つける必要があります。)
paste -- "$list1.txt" "list2.txt" |
while IFS=$'\t' read -r file1 file2 rest; do
diff -q -- "$file1" "$file2"
case $? in
0) status='same';;
1) status='different';;
*) status='ERROR';;
esac
echo "$status $file1 $file2"
done
空白行をスキップする場合は、各ファイルで個別に行う必要がありますpaste
。1つのファイルの空白行と別のファイルの非空白行が一致する可能性があるためです。使用できますgrep
して、非空白行をフィルタリング。
paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
…
2つのファイルの長さが異なる場合は、空になることに注意してください $file2
(どちらのリストが最初に終了したかに関係なく)。
方法2:2つのファイルをループする
whileループの状態に好きなだけ複雑なコマンドを入れることができます。配置read file1 <&3 && read file2 <&4
すると、両方のファイルに読み込む行がある限り、つまり1つのファイルがなくなるまでループが実行されます。
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
空白行をスキップする場合、2つのファイルを個別にスキップする必要があるため、少し複雑になります。簡単な方法は、問題を2つの部分に分けることです。1つのファイルから空白行をスキップし、非空白行を処理します。空白行をスキップする1つの方法はgrep
、上記のように処理することです。<
リダイレクト演算子と<(
コマンドの中断を開始する演算子の間の必要なスペースに注意してください。
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")
別の方法は、read
空行をスキップするように動作する関数を作成することです。この関数はread
、ループで呼び出すことで機能します。関数である必要はありませんが、関数を使用するのが最良の方法です。コードを整理するためと、そのコードを2回呼び出す必要があるためです。関数で${!#}
は、bash構造のインスタンスで、${!VARIABLE}
名前がの値である変数の値に評価されVARIABLE
ます。ここで、変数は#
位置パラメータの数を含む特別な変数で${!#}
あり、最後の位置パラメータも同様です。
function read_nonblank {
while read "$@" &&
[[ ${!#} !~ [^[:space:]] ]]
do :; done
}
while read_nonblank -u 3 -r file1 && read_nonblank -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
diff
。