file1="/scratch/abc/osx.xrts"
のような2つのファイルがありますfile2="/scratch/unzip/abc/osx.xrts"
。
diff
行末を無視してコマンドを実行しています。コマンドとコードは次のとおりです。
diff --strip-trailing-cr file1 file2 > /dev/null
if [ $? -eq 0 ]; then
echo "no diff"
elif if [ $? -eq 1 ]; then
echo "there is diff"
else
echo "something is wrong"
fi
観察結果
これにより、内容file1
とfile2
内容が同じであれば、「違いなし」という結果が得られます。ただし、問題はコンテンツfile1
とコンテンツの間にわずかな違いがある場合に発生します。file2
この場合、diff
上記のようにコマンドを実行し、違いを印刷して終了します。 if-else部分にはまったく入らない。
for
多くのファイルを比較する必要があるため、このコードをループ(ここでは表示されていません)として実行しています。しかし、私のスクリプトは違いを印刷して違いがある最初のファイルのペアを見つけるとすぐに終了し、if-else部分にはまったく到達しません。何が間違っているのかわかりません。どんな助けでも大変感謝します。
私が期待する結果
ファイル間に違いがある場合は、違いを印刷しないでください。代わりに、そのセクションに移動してelif if [ $? -eq 1 ]; then
「違いがあります」を印刷してから、他のファイルを比較してfor
ループを続行する必要があります。
答え1
マイナーな印刷上のエラーを修正した後、コードは次のようになります。
(1) diff --strip-trailing-cr "$file1" "$file2" > /dev/null
(2) if [ $? -eq 0 ]; then
(3) echo "no diff"
(4) elif [ $? -eq 1 ]; then
(5) echo "there is diff"
(6) else
(7) echo "something is wrong"
(8) fi
(もちろん、上記の画像の行番号は説明のためのものであり、スクリプトの一部ではありません。)これには誰も指摘していない微妙なバグがあります。終了状態が何であれ、 diff
その echo "something is wrong"
部分は決してそうではありません。達した。diff
コマンドを、、など(exit "$1")
の数字に置き換えてから、引数として渡すことで簡単にテストできます。0
1
2
3
問題は、これが$?
揮発性変数であることです。もちろん、2行はdiff
1行()コマンドの終了状態です。ただし、4行目は
$?
2行目のテストコマンドの終了状態です[ $? -eq 0 ]
。終了状態がdiff
0でない場合、[ $? -eq 0 ]
テストは$?
1に設定されます。いつもthere is diff
ニュースを受けました。
この問題を処理する方法はいくつかあります。 1つは、終了状態を安定したdiff
変数に保存することです。
diff --strip-trailing-cr "$file1" "$file2" > /dev/null
diff_exit_status=$?
if [ "$diff_exit_status" -eq 0 ]; then
echo "no diff"
elif [ "$diff_exit_status" -eq 1 ]; then
echo "there is diff"
else
echo "something is wrong"
fi
もちろん、より短い変数名を使用することもできます。
2番目は、 case
次の文を使用することです。
diff --strip-trailing-cr "$file1" "$file2" > /dev/null
case "$?" in
(0)
echo "no diff"
;;
(1)
echo "there is diff"
;;
(*)
echo "something is wrong"
esac
答え2
file1
とが存在し、同じ場合は、file2
コードスニペット(表示されている)に構文エラーが生成されますunexpected end of file
。これはif
、シェルが一致するステートメントを検出する終了していないステートメントによって引き起こされますfi
。これはelif if
代わりにhasによって引き起こされますelif
。コードの残りの部分に他のバグがない場合、報告された問題は解決されます。
また、2つの別々のステートメントでコマンドを実行して終了ステータスを確認するのではなく、コマンドの終了コードを1行で直接確認できます。
if diff --strip-trailing-cr file1 file2 > /dev/null; then
echo "no diff"
elif [ $? -eq 1 ]; then
echo "there is diff"
else
echo "something is wrong"
fi
ちなみに、シェルスクリプトを書くときにそれをチェックするのは本当に便利です。ShellCheck – シェルスクリプト解析ツール。