zsh globbingを使用してパスコンポーネントを選択的に指定するには?

zsh globbingを使用してパスコンポーネントを選択的に指定するには?

次のディレクトリ構造があるとします。

% tree foo 
foo
├── bar
│   └── baz
└── baz

2つのエレガントなマッチング方法foo/bar/baz そして foo/baz?つまり、bar/パスのコンポーネントを選択的にする方法は何ですか?

foo/*/baz有効な拡張子ではないfoo/bar/bazので一致します。foo//bazオプションのグループを試しましたが、次のようになります。

% set -o KSH_GLOB
% echo foo/?(bar)/baz

また、foo/bar/baz同じ理由で(foo//baz有効な拡張子ではない)に拡張されます。/によると、グループ内にaを含めることは通常違法であるため、たとえばzshexpn(1)エラーfoo/?(bar/)bazが発生します。

特に奇妙なケースではないようですが、Google検索やSE検索では関連コンテンツが見つかりません。

答え1

これはkshとzsh globの問題です。中かっこを使用できます。

echo foo{,/bar}/baz
echo foo{,/*}/baz    # you probably don't want this one, see below

ただし、校正器は全体ではなく、校正器が十分に近いかどうかは、実行している作業によって異なります。

主な質問は、どのファイルが存在するのか、一部のファイルが存在しない場合はどうなるのかということです。foo{,/bar}/baz2つの単語に展開され、foo/bazファイルfoo/bar/bazが存在するかどうか。ワイルドカードを使用すると、デフォルトでfoo{,/*}/baz一致するファイルがないとエラーが発生します。存在foo/*/bazしても同じです。foo/baz次の方法でこの問題を解決できます。N ワイルドカードフラグ:

echo foo{/*,}/baz(N)

これにより、一致する既存のファイルのリストfoo/*/baz(リストが空であっても)に展開されます。これは、機能すると得られるものとfoo/baz同じです。foo/(*/|)/baz(N)一方、単純に同等のものはありませんfoo/(*/|)/baz。一致するものがない場合にエラーが発生するには、自分で行う必要があります。

bazes=(foo{,/*}/baz(N))
if (($#bazes == 0)); then echo >&2 "No bazes are belong to us"; return 1; fi

中かっことglobのもう1つの違いは、中かっこ内の順序によって拡張順序が決定されることです。たとえば、編集時間に関係なく、echo foo{,/*}/baz(Nom)常に最初に入力します。foo/baz

答え2

誤って> 1つの「オプションの」パス名コンポーネントを一致させた場合、問題はありません。次のことができます。

% set -o EXTENDED_GLOB
% echo foo/(bar/)#baz

foo/barこれはとに一致しますfoo/bar/bazが、foo/bar/bar/baz等とも一致します。

答え3

両方の場所で一致するファイルが必要かどうか明示的に話していません。ただまたはみんな彼らは木にあります。すべての項目を一致させるオプションがある場合は、次のものを使用できます**

% mkdir -p foo/{bar,asdf/asdf,}/baz
% echo foo/**/baz       
foo/asdf/asdf/baz foo/bar/baz foo/baz

Bashでも動作します(globstar有効)。

$ shopt -s globstar
$ echo foo/**/baz       
foo/asdf/asdf/baz foo/bar/baz foo/baz

(zshとBashの間にはいくつかの注意点/違いがあります**。ツリーのシンボリックリンクです。)

関連情報