ディレクトリ(と呼ばれる)に2つのファイル(と呼ばれるdir
)のうちの1つが含まれていますが、ファイルが1つもなく両方が含まれていないことを確認する必要があります。filea
fileb
理想的な解決策は、述語間でXOR演算を使用することです。
if [ -f dir/filea ] ^ [ -f dir/fileb]
then
echo Structure ok
# do stuff
fi
ただし、シェルはこれを^
XOR演算子としてサポートしておらず、[
オプションなしでコマンドと一緒に-X
または--xor
同様の負の-a
同等-o
性を使用することも機能しません。
if ! [ -f dir/filea -eq -f dir/fileb ]
# or
if ! [ -f dir/filea = -f dir/fileb ]
このような本格的なAND / OR式を使用せずにこれを達成する方法はありますか?
if { [ -f dir/filea ] || [ -f dir/fileb ]; } && ! { [ -f dir/filea ] && [ -f dir/fileb ]; }
?
最後の表現は読みにくくなり、確かに私の実際のパスはdir/fileX
。
編集する:POSIX準拠のバージョンを目指していますが、他のシェルに関連する拡張にはオープンです(主に好奇心が強いため、sh
他のプロジェクトでまたはbash
使用しているためksh93
便利です)。
ベストアンサー1
test ...
または、コマンドの終了コード[ ... ]
はテスト結果です。変数を使用して個々のテスト結果を保存し、後で比較することができます。
[ -f dir/filea ]
testA=$?
[ -f dir/fileb ]
testB=$?
if [ "$testA" -ne "$testB" ]
then
echo "exactly one file"
else
echo "both files or none"
fi
これにより、[
両方のテストでゼロ以外の終了コードが生成される可能性があります。
仕様によるとhttps://pubs.opengroup.org/onlinepubs/007904875/utilities/test.html、終了コードは>1
「エラーが発生しました」を意味します。[
エラーが報告されたときに何が起こるかを定義する必要があります。
これを防ぐには、次のような条件付き変数割り当てを使用できます。コサロナンダの答え...
testA=0
testB=0
[ -f dir/filea ] || testA=1
[ -f dir/fileb ] || testB=1
if [ "$testA" -ne "$testB" ]
then
echo "exactly one file"
else
echo "both files or none"
fi
...またはコメントに記載されているように、否定を使用して値が0
orであることを確認してください1
。
(「2.9.2パイプライン」 - 「終了ステータス」を参照)https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_02)
! [ -f dir/filea ]
testA=$?
! [ -f dir/fileb ]
testB=$?
if [ "$testA" -ne "$testB" ]
then
echo "exactly one file"
else
echo "both files or none"
fi
どちらのバリエーションも「ファイルが存在しません」と同じ方法でエラーを処理します。