Bashのマニュアルによると、有効になっている場合、このパターンはextglob
(区切り)@(pattern-list)
のすべてのパターンと一致する必要があります。ここでは期待どおりに動作します。pattern-list
|
$ shopt -s extglob
$ ls -ld /@(.|usr)/@(.|local)/@(.|share)/
drwxr-xr-x 50 root root 4096 Sep 2 16:39 /./././
drwxr-xr-x 12 root root 4096 Oct 15 2018 /usr/././
drwxrwsr-x 10 root staff 4096 Oct 15 2018 /usr/local/./
drwxrwsr-x 10 root staff 4096 Oct 15 2018 /usr/local/share/
drwxr-xr-x 725 root root 20480 Sep 2 16:42 /usr/./share/
ただし、3つのパターンリストのそれぞれで代替を置き換えると、一致する必要があるほとんどのディレクトリが消えます。
$ ls -ld /@(usr|.)/@(local|.)/@(share|.)/
drwxrwsr-x 10 root staff 4096 Oct 15 2018 /usr/local/share/
存在しないサブディレクトリの場合も同様です。ここでは動作します:
$ ls -ld /@(.|usr)/@(.|foo)/@(.|share)/
drwxr-xr-x 50 root root 4096 Sep 2 16:39 /./././
drwxr-xr-x 12 root root 4096 Oct 15 2018 /usr/././
drwxr-xr-x 725 root root 20480 Sep 2 16:42 /usr/./share/
しかし、ここではそうではありません。
$ ls -ld /@(usr|.)/@(foo|.)/@(share|.)/
ls: cannot access '/@(usr|.)/@(foo|.)/@(share|.)/': No such file or directory
ここで何が起こっているのでしょうか?この動作はどこかに文書化されていますか、それとも単純なバグですか? (これはGNU bashバージョン4.4.12(1)です。)
答え1
bash-4.3以前は「.」用語が一致しませんでした。 bash(1), v5.0, 一部からパス名拡張:
When a pattern is used for pathname expansion, the character ``.'' at the start of a name or immediately following a slash must be matched explicitly, unless the shell option dotglob is set. The filenames ``.'' and ``..'' must always be matched explicitly, even if dotglob is set.
ここでの動作の説明は少しあいまいですが、いいえ「.」は、すべての(サブ)パターンの先頭になければならないことを意味し、以下を介して証明できます。
$ echo /@(usr|.)/@(local|.)/@(share|.)/
/usr/local/share/
$ echo /@(usr|..)/@(local|..)/@(share|..)/
/../../../ /usr/../../ /usr/local/../ /usr/local/share/
したがって、問題は「.」に固有のものです。 「..」ではありません。
私はこれがバグだと信じています。extglob_skipname()
,while (t = glob_patscan (pp, pe, '|')) { ... }
ループの 218 行目からこのパターンの最後の項目が正しく処理されないので ( の先行 "." 抑制ロジックと相互作用skipname()
) "." は一致しませんが ".." は一致します。 (glob_patscan
別名Macro GamesのおかげですPATSCAN
。)
次のいずれも機能します。
$ echo /@(usr|.|)/@(local|.|)/@(share|.|)/
/./././ /usr/././ /usr/./share/ /usr/local/./ /usr/local/share/
$ echo /@(usr|.|.)/@(local|.|.)/@(share|.|.)/
/./././ /usr/././ /usr/./share/ /usr/local/./ /usr/local/share/
したがって、答えは、サブパターンの順序が重要でも重要でもないということです。ただし、最後のエントリが「.」の場合、バグが問題を引き起こす可能性があるようです。