Bashに複数のパターンがあるかどうかを確認する方法

Bashに複数のパターンがあるかどうかを確認する方法

**ワイルドカードを含むいくつかのパターンがあるので、次のように設定します。

foo/**/bar.xml
foo/**/baz.xml

サンプルディレクトリツリーがあります。

$ tree foo/
foo/
└── deep
    ├── baz.xml
    └── even
        └── deeper
            └── baz.xml

これらのパターンが満たされていることを確認する最も簡単な方法は何ですか?正確に言うと、ゼロ以外の値を返します。ない場合のみ見つけることができます。これまで私が考えたのはglobstarandを使うことです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'または(と共にextglobhas 'foo/**/@(bar|baz).xml'またはhas 'foo/**/bar.xml' || has 'foo/**/baz.xml'

最初のマッチンググローブで停止します。

より効率的にし、最初の一致で停止するには、zsh反対と対応するY1glob修飾子を使用できます。

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

グローバルオペレータを引用する必要はありません。

おすすめ記事