名前
glob - パス名を glob する
説明
昔々 Unix V6 では、ワイルドカードパターンを展開する /etc/glob と言うプログラムがあった。その後すぐに、 この機能はシェルに組み込まれるようになった。
今日では、この機能をユーザープログラムからも実行できるよう、 glob(3) というライブラリルーチンも存在している。
glob の規則を以下に述べる (POSIX.2 3.13)。
ワイルドカードマッチ
文字列に ?, *, [ が含まれていると、 それはワイルドカードパターンとみなされる。 「glob する」というのは、ワイルドカードパターンを展開して、 そのパターンにマッチするパス名のリストを得ることである。 マッチは以下のように定義される。
(ブラケット外部の) ? はあらゆる単一の文字にマッチする。
(ブラケット外部の) * はあらゆる文字列にマッチする。 空文字列 (empty string) にもマッチする。
文字クラス (character class)
[...] と言う表記は、先頭の [ に続く最初の文字が ! でなければ、 ブラケットの中に含まれている文字のどれか一つにマッチする。 ブラケットの内部に含まれる文字列は空であってはならない。 したがって ] も最初の文字に指定すればブラケットの内部に含めることができる。 (つまり [][!] は [, ], ! の 3 文字のどれかにマッチする。)
領域指定 (range)
特殊な表記法が一つ存在する。- を挟む二つの文字は領域指定となる。 (つまり [A-Fa-f0-9] は [ABCDEFabcdef0123456789] と等価となる。) - 文字そのものを入れたい場合は、 ブラケットの先頭または最後の文字に指定すればよい。 (つまり []-] は二つの文字 ] と - にマッチし、[--0] は -, ., 0 の 3 文字にマッチする。 この間の / にはマッチしない。後述を参照。)
補集合 (complementation)
[!...] と言う表記は、ブラケットの内部に含まれない単一の文字にマッチする (ただし先頭にある ! は除外)。 (つまり [!]a-] は ], a, - 以外のすべての文字の、どれか一つにマッチする。)
バックスラッシュ \ を前置すれば、 ?, *, [ は通常の文字として扱われる。 またはシェルのコマンドラインの一部に指定する場合は、 クォートで囲っても同じ効果が得られる。ブラケットの内部では、 これらの文字はその文字自身だけを意味する。 すなわち [[?*\] は [, ?, *, \ のどれか一文字にマッチする。
パス名 (pathname)
glob 動作は、パス名のそれぞれの部分に独立に適用される。 パス名に存在する / は ? や * ワイルドカードにはマッチしない。 また [.-0] のような領域指定にもマッチしない。 領域指定は陽に / 文字を含むことはできない。これは文法エラーとなる。
. で始まるパス名では、この文字は陽にマッチさせなければならない。 (つまり rm * は .profile を削除しない。また tar c * ではすべてのファイルはアーカイブされない。 tar c . の方が良い。)
空のリスト
先に与えた、わかりやすく簡単なルール、 「ワイルドカードパターンをマッチしたパス名のリストに展開する」と言うのは、 オリジナルの Unix における定義であった。 これはパターンが空のリストに展開されることも許可されていた。 例えば xv -wait 0 *.gif *.jpg において、*.gif ファイルが全くない場合でも、 これは空のリストに展開されるため、エラーにならない。 しかし POSIX では、文法的に正しくないパターンや、 マッチがなかったパターンは、 そのまま変更されずに残されることになっている。 bash では allow_null_glob_expansion=true を指定することで、以前の振る舞いに設定することができる。
(同様の問題は別のところでも起こっている。例えば、古いスクリプトにおける rm find . -name "*~" のような記述は、新しいスクリプトでは rm -f nosuchfile find . -name "*~" のようにしなければならない。さもないと rm を引き数リストなしで呼び出す可能性があり、 エラーメッセージが出てしまう。)
注意
正規表現
ワイルドカードパターンは正規表現と多少似ているが、しかしこの両者は異なる。 まず第一に、前者がファイル名にマッチするのに対して、 後者はテキストにマッチする。第二に、ルールも同じではない。 例えば正規表現における * は、 前置された文字の 0 以上の繰り返しを表す。
正規表現にもブラケット表現はあるが、否定は ^ でなされる。 POSIX ではワイルドカードパターンにおける [^...] を未定義であるとしている。
文字クラスと国際化
領域指定は、もともとはもちろん ASCII における順序並びを意味していた。 したがって [ -%] は [ !"#$%] の意味であり、 [a-z] は 「すべての小文字」の意味であった。 Unix の実装の中には、これを拡張したものが存在し、 そこでは X-Y という領域指定は、X のコードと Y のコードに挟まれたコードを持つ文字すべてを表すようになっていた。 しかし、これにはユーザーがローカルなシステムにおける 文字コードを知らなければならず、 さらにローカルなアルファベットに対する照合順序 (collating sequence) が文字コードの順序と異なっている場合には不便であった。 (訳注: collating sequence に関しては regex(7) を参照して下さい。) したがって POSIX では、ワイルドカードパターンと正規表現の双方において、 ブラケット表記を大幅に拡張している。 これまで我々は、ブラケット表記には三つの要素が含まれうることを見てきた。 すなわち (i) 否定、(ii) 単一の文字、(iii) 領域指定、の三つである。 POSIX では、領域指定をより国際化に便利なように定義しており、 また三つのタイプをブラケット表記の要素として追加している。
(iii) 領域指定 X-Y は X と Y に挟まれた (両端含む) すべての文字を意味する。 このとき、カレントロケール (current locale) の LC_COLLATE カテゴリで定義されている照合順序が用いられる。
(iv) 名前付き文字クラス: 以下のようなものである。
[:alnum:] [:alpha:] [:blank:] [:cntrl:]
[:digit:] [:graph:] [:lower:] [:print:]
[:punct:] [:space:] [:upper:] [:xdigit:]
(v) 照合順序におけるシンボル: [.ch.] や [.a-acute.] のように [. と .] で挟まれた文字列は、カレントロケールで定義された照合順序の要素となる。 ある一つの要素が複数の文字からなる場合もありうることに注意。
(vi) 等価クラス表現 (equivalence class expressions): [=a=] のように [= と =] とで挟まれた文字列である。 これは等価クラスのメンバーである照合順序の要素すべてになる。 等価クラスはカレントロケールで定義されているものになる。 例えば、[[=a=]] は [a[.a-acute.][.a-grave.][.a-umlaut.][.a-circumflex.]] と等価である (Latin-1 表記では [a\{a}\{a}\"{a}\^{a}] も同じ。 [訳注] 日本語の roff ページでは latin1 コードが出ないので、 ここでは TeX 表記で記載)。