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

おすすめ記事