この問題を解決するには、globが/a/b/c/*
一致するエントリを生成しないと仮定します。
これは、次のテストが失敗する必要があることを意味します(つまり、ゼロ以外の値を生成する必要があります$?
)。
[[ -n /a/b/c/*(#qN) ]]
実際にこのような場合がありますもし(zsh)コマンドラインから直接テストを実行します。しかし、私が続けるなら全く同じテストスクリプトは期待される動作ではなく成功します。
そのフラグを使用して同じスクリプトを実行すると、-x
結果トレースにテストが次のように表示されます。
[[ -n '/a/b/c/*(#qN)' ]]
テストパラメータの周りに一重引用符が表示される理由を理解できません。スクリプトソースコードには引用符はまったくありません。
zshがこれらの一重引用符を自動的に挿入すると、テキストが成功した理由が説明されます。
質問:
- この式のコマンドラインバージョンとスクリプトバージョンの間に違いがあるのはなぜですか?
- スクリプトのテストが(正しく)失敗するようにするにはどうすればよいですか?
答え1
CONDITIONAL EXPRESSIONS
zsh マニュアルのセクション:
どの形式の条件付き引数でもファイル名の生成は行われません。ただし、通常のシェル拡張が適用され、EXTENDED_GLOBオプションが適用されている場合は、文字列の末尾に(#q)形式の明示的なglob修飾子を使用して強制的に適用できます。
つまり、スクリプト内でextendedglob
オプションが設定されていない場合は、/a/b/c/*(#qN)
リテラル文字列として扱われます。
答え2
globがファイルと一致することを確認するためのより良いイディオム(IMO)は次のとおりです。
()(($#)) /a/b/c/*(NY1)
extendedglob
これには特別な状況は必要ありません[[ -n ...(#qN) ]]
。そしてY1
最初のプレイで止まるので、より効率的です。
(($#))
これは、匿名関数の引数がゼロ以外の場合にtrueを返す算術式である匿名関数にglob拡張を渡すように機能します。
これを次のように拡張できます。
if ()(( $# >= 3 )) /a/b/c*(NY3); then
echo there were at least 3 matching files.
fi