
次のように、各ディレクトリにテキストファイルを含む2つのディレクトリを作成するとします。
mkdir "Directory1"
mkdir "Directory2"
touch "Directory1/fileclass1_"{1..5}".txt"
touch "Directory1/fileclass2_"{1..5}".txt"
touch "Directory2/fileclass1_"{1..5}".txt"
touch "Directory2/fileclass2_"{1..5}".txt"
次のようにして、すべてのファイルが内部にあることを確認するとします。
A=( "Directory1" "Directory2" )
B=( "fileclass1" "fileclass2" )
for a in "${A[@]}"; do
for b in "${B[@]}"; do
for i in {1..5}; do
name="${a}/${b}*${i}.txt"
[[ ! -e $name ]] && echo "$name Does Not Exist"
done
done
done
このリターン
Directory1/fileclass1*1.txt Does Not Exist
Directory1/fileclass1*2.txt Does Not Exist
...
ただし、二重括弧を単一の括弧に置き換えると、次のような結果が得られます。
A=( "Directory1" "Directory2" )
B=( "fileclass1" "fileclass2" )
for a in "${A[@]}"; do
for b in "${B[@]}"; do
for i in {1..5}; do
name="${a}/${b}*${i}.txt"
[ ! -e $name ] && echo "$name Does Not Exist"
done
done
done
何も返さず、これはすべてのファイルが実際にそこにあることを示します。
この場合、二重括弧は失敗しますが、単一の括弧が機能するのはなぜですか?私は常に二重括弧を使用する必要があると仮定します。文字列一致のワイルドカードは私が持ってはいけないものを生成しますか?
答え1
条件付き-e
演算子は、特定の名前のファイルが存在するかどうかをテストします。パターンマッチングを行いません。ワイルドカードパターンに一致するファイルが1つ以上あるかどうかをテストするのではなく、名前にアスタリスクがあるファイルが存在するかどうかをテストします[[ -e fileclass1*1.txt ]]
。fileclass1*1.txt
fileclass1*1.txt
単一の括弧は引用されていない[ ! -e $name ]
ため、$name
値はname
ワイルドカードの置き換えとトークン化を受けます。name
値がある場合、Directory1/fileclass1*1.txt
ワイルドカードパターンに一致するファイルの数によって効果が異なります。
- パターンがどのファイルとも一致しない場合は拡張されません。その後、オペレータは
-e
ファイル名がDirectory1/fileclass1*1.txt
存在しないことを確認するので、[ ! -e $name ]
これは本当です。 - パターンが単一のファイルと一致する場合、そのファイルの名前に置き換えられます。次に、オペレーターは
-e
ファイル名が存在することを確認するので[ ! -e $name ]
false です。 - パターンが複数のファイルと一致する場合は、一致するファイル名のリストに置き換えられ、条件によって構文エラーが発生します。この場合、
[ ! -e $name ]
エラーメッセージが表示され、障害状態が返されます。
特殊な構文(ただし、[[ -e $name ]]
効果が異なります。単語分割やワイルドカード拡張は内部的には行われません。[[ … ]]
[
[[ … ]]
実際の問題を解決するには、次を参照してください。スクリプトを実行するためにパターンに一致するファイルがあるかどうかをテストします。
1競合状態が発生した場合を除き、ファイルは、シェルがワイルドカードパターンを拡張するためにディレクトリの内容を一覧表示する時間と、オペレータがファイルが存在することを確認する時間の間に削除されます。-e