
**ワイルドカードを含むいくつかのパターンがあるので、次のように設定します。
foo/**/bar.xml
foo/**/baz.xml
サンプルディレクトリツリーがあります。
$ tree foo/
foo/
└── deep
├── baz.xml
└── even
└── deeper
└── baz.xml
これらのパターンが満たされていることを確認する最も簡単な方法は何ですか?正確に言うと、ゼロ以外の値を返します。ない場合のみ見つけることができます。これまで私が考えたのはglobstar
andを使うことですnullglob
。ただし、ls
これはオプションではなく、パターンが満たされていないかのように現在のディレクトリを一覧表示します。そのため、echo
次のように活用する必要があります。
$ (shopt -s globstar nullglob; echo foo/**/bar.xml foo/**/baz.xml) | grep .
foo/deep/baz.xml foo/deep/even/deeper/baz.xml
$ echo $?
0
そして
$ (shopt -s globstar nullglob; echo foo/**/bar.xml foo/**/beque.xml) | grep .
$ echo $?
1
はい。動作します。しかし、たぶん私が何かを逃しているかもしれません。よりシンプルでエレガントこの目標を達成する方法は?
答え1
次の機能を使用できます。
non_empty() (($#))
has() (
IFS=
set +o noglob
shopt -s globstar nullglob extglob
shopt -u failglob # which has precedence over nullglob!
for glob do
non_empty $glob && return
done
false
)
if has 'foo/**/bar.xml' 'foo/**/baz.xml'; then
echo matches found
fi
(またはhas 'foo/**/ba[rz].xml'
または(と共にextglob
)has 'foo/**/@(bar|baz).xml'
またはhas 'foo/**/bar.xml' || has 'foo/**/baz.xml'
)
最初のマッチンググローブで停止します。
より効率的にし、最初の一致で停止するには、zsh
反対と対応するY1
glob修飾子を使用できます。
has() {
local glob
for glob do
()(($#)) $~glob(NY1) && return
done
false
}
non_empty
(匿名関数にもインライン化されます。)
**/
再帰的機能は90年代初めのzshで提供されており、デフォルトで有効になっています(bashによってコピーされましたが、2000年代後半にはデフォルトで有効になっていません)。交換はhas 'foo/**/(bar|baz).xml'
inで行われますzsh
。
では、zsh
次のこともできます。
alias has='noglob has'
できること:
if has foo/**/bar.xml foo/**/baz.xml; then
echo matches found
fi
グローバルオペレータを引用する必要はありません。
答え2
位置引数リストをオーバーライドできる場合:
shopt -s globstar nullglob
set -- foo/**/bar.xml foo/**/baz.xml
if [ "$#" -ne 0 ]; then
echo matches found
fi
これは、位置パラメータリストをワイルドカードパターンと一致する名前に設定します。有効なので、nullglob
一致するものがない場合、リストは空です。値は$#
位置引数リストの長さです。
サブシェルで実行するというアイデアを活用してください。
( shopt -s globstar nullglob; set -- foo/**/bar.xml foo/**/baz.xml; [ "$#" -ne 0 ] )
位置引数リストの代わりに配列を使用します。
shopt -s globstar nullglob
names=( foo/**/bar.xml foo/**/baz.xml )
if [ "${#names[@]}" -ne 0 ]; then
echo matches found
fi