複数の文字列を作る ブレース展開 は、別の記事で紹介しました。この記事では、複数のファイル名やディレクトリ名をパターンで指定できる、パス名展開(ワイルドカード)の使い方を、実行例と図で説明します。
ワイルドカードは、任意の文字列などを表す特殊文字です。コマンドを実行する前に、bash がワイルドカードを含むパターンを、一致するファイル名やディレクトリ名に置き換えます。
*(任意の文字列)と?(任意の1文字)で名前のパターンを書けること。パターンは、コマンドではなくシェルが展開すること[ ]で文字の候補や範囲を指定でき、!で除外、[[:upper:]]などの文字クラスで文字の種類を指定できること{ }はパス名展開ではなくブレース展開で、パス名展開より先に処理されること
パス名展開とワイルドカード
シェルは、コマンドラインの中にワイルドカードを含む単語があると、その単語を、一致する名前に置き換えてからコマンドを実行します。たとえば echo d* では、echo が d* を受け取るのではなく、シェルが置き換えた data1 data11 … が echo に渡されます。置き換わった名前は、ロケールの照合順に並んだ複数の引数になります。
echo d* は、シェルが名前に置き換えてから echo に渡されるパスを含まない記述(d* など)は、カレントディレクトリの名前が対象です。使えるワイルドカードは次のとおりです。
| 記号 | 意味 | 例 |
|---|---|---|
| * | 任意の文字列(空の文字列も含む) | d*、*11 |
| ? | 任意の1文字 | ???11 |
| [ABC] | 角括弧の中の、どれか1文字 | [ABC]* |
| [a-f] | 範囲の中の、どれか1文字 | [a-f]* |
| [!1-3] | 範囲に含まれない1文字([^1-3] も同じ) | *[!1-3][1-3][1-3] |
| [[:upper:]] | 文字クラスに含まれる1文字 | [[:upper:]]* |
この記事では、次のファイルとディレクトリがあるカレントディレクトリで試します。drwx… で始まる dir1 と dir11 がディレクトリで、ほかはサイズ 0 のファイルです。
hirotano@linux-1:~$ ls -l 合計 8 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:17 1-music -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:17 11-music -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:17 2-music -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:05 Backup111 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:05 Backup222 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:05 Backup333 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:06 IMAGE -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:05 IMAGE1 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:06 IMAGE12 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:04 data1 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:04 data11 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:04 data111 drwxrwxr-x 2 hirotano hirotano 4096 12月 24 06:03 dir1 drwxrwxr-x 2 hirotano hirotano 4096 12月 24 06:03 dir11 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:04 file1 -rw-rw-r-- 1 hirotano hirotano 0 12月 24 06:04 file2.txt
パターンがどの名前に展開されるかは、echo で確認できます。rm や mv などに使う前に、echo で展開結果を確かめておくと、意図しない名前を巻き込む失敗を防げます。
任意の文字列(*)
* は、任意の文字列に一致します。空の文字列にも一致します。
echo * は、カレントディレクトリのすべての名前に展開されるhirotano@linux-1:~$ echo *
1-music 11-music 2-music Backup111 Backup222 Backup333 IMAGE IMAGE1 IMAGE12 data1 data11 data111 dir1 dir11 file1 file2.txt
カレントディレクトリにある16個の名前が、すべて展開されました。
先頭文字を指定した展開
d* は、先頭が d で、そのあとが任意の文字列の名前に一致します。
d* は d で始まる名前に一致するhirotano@linux-1:~$ echo d*
data1 data11 data111 dir1 dir11
末尾の文字列を指定した展開
*11 は、末尾が 11 の名前に一致します。Backup111 は、末尾の2文字が 11 なので一致します。
*11 は 11 で終わる名前に一致するhirotano@linux-1:~$ echo *11
Backup111 data11 data111 dir11
開始、および終了の文字列を指定して展開
d*11 は、先頭が d で、末尾が 11 の名前に一致します。
d*11 は d で始まり 11 で終わる名前に一致するhirotano@linux-1:~$ echo d*11
data11 data111 dir11
* は空の文字列にも一致するので、d*11 は、たとえば d11 という名前にも一致します。
また、* や ? は、先頭がピリオド(.)の名前(隠しファイル)には一致しません。/(パスの区切り)にも一致しないので、サブディレクトリの中の名前は、dir*/* のようにパスを区切って書きます。
任意の1文字(?)
? は、任意の1文字に一致します。文字数が決まっている名前を指定するときに使います。????? は、? が5つなので、5文字の名前に一致します。
????? は5文字の名前に一致するhirotano@linux-1:~$ echo ?????
IMAGE data1 dir11 file1
先頭の文字数を指定した展開
???11 は、任意の3文字のあとに 11 が続く、5文字の名前に一致します。
???11 は任意の3文字のあとに 11 が続く名前に一致するhirotano@linux-1:~$ echo ???11
dir11
末尾の文字数を指定した展開
f*.??? は、先頭が f で、ピリオドのあとが任意の3文字(拡張子が3文字)の名前に一致します。* と ? は、1つのパターンの中で組み合わせられます。
f*.??? は f で始まり、ピリオドのあとが3文字の名前に一致するhirotano@linux-1:~$ echo f*.???
file2.txt
文字指定([ ])
角括弧 [ ] の中に書いた文字のうち、どれか1文字に一致します。1文字を指定するので、複数の文字に一致させたいときは * と組み合わせます。
指定文字のいずれかで展開
[ABC]* は、先頭が A、B、C のどれかで、そのあとが任意の文字列の名前に一致します。
[ABC]* は A、B、C のどれかで始まる名前に一致するhirotano@linux-1:~$ echo [ABC]*
Backup111 Backup222 Backup333
指定した文字範囲で展開
ハイフン(-)を使うと、文字の範囲を指定できます。[a-f]* は、先頭が a から f のどれかの名前に一致します。
[a-f]* は a から f のどれかで始まる名前に一致するhirotano@linux-1:~$ echo [a-f]*
data1 data11 data111 dir1 dir11 file1 file2.txt
a-f のような範囲の並びは、bash の設定によって、ロケールの照合順で解釈される場合があります。その場合、[a-f] に大文字(B など)が含まれることがあります。shopt globasciiranges で現在の設定を確認でき、on のときは、ロケールに関係なく ASCII の並びで解釈されます。大文字か小文字かを確実に指定したいときは、あとで説明する [[:upper:]]、[[:lower:]] を使います。
指定した数字範囲で展開
数字も範囲で指定できます。*[1-3][1-3][1-3] は、末尾の3文字が、すべて 1 から 3 のどれかの名前に一致します。data11 は、末尾の3文字が a11 なので一致しません。
*[1-3][1-3][1-3] は末尾が1から3の数字3つの名前に一致するhirotano@linux-1:~$ echo *[1-3][1-3][1-3]
Backup111 Backup222 Backup333 data111
指定した文字を含めず展開
角括弧の先頭に ! を付けると、その範囲に含まれない1文字に一致します。*[!1-3][1-3][1-3] は、末尾の3文字が、「1 から 3 以外の1文字」と「1 から 3 のどれか2文字」の順で並ぶ名前に一致します。
*[!1-3][1-3][1-3] の一致するようすhirotano@linux-1:~$ echo *[!1-3][1-3][1-3]
IMAGE12 data11 dir11
IMAGE12 は E、data11 は a、dir11 は r が、1から3以外の文字として一致しました。Backup111 は、末尾の3文字がすべて 1 なので、一致しません。! の代わりに ^ でも同じ指定ができます。
文字列指定({ })
中括弧 { } は、ここまでのワイルドカードとは別の、ブレース展開です。コンマで区切った文字列を、順番に展開します。{file1,data*} は、file1 と data* に展開されます。
echo {file1,data*} は、ブレース展開のあとにパス名展開が行われるhirotano@linux-1:~$ echo {file1,data*}
file1 data1 data11 data111
ブレース展開が先に処理され、そのあとで、data* がパス名展開で data1 data11 data111 に置き換わります。ブレース展開は、ファイルがあるかどうかを調べずに展開するので、存在しない名前でも展開されます。ブレース展開の詳しい使い方は、【図解:bash】ブレース展開の使用方法 にまとめています。
文字クラス定義([[: :]])
文字の種類は、[[:クラス名:]] の形で指定できます。[[:upper:]] は大文字の1文字、[[:lower:]] は小文字の1文字、[[:digit:]] は数字の1文字です。
[[:クラス名:]] の形で書く| クラス名 | 意味 |
|---|---|
| alpha | 英字 |
| digit | 数字(0 から 9) |
| alnum | 英数字 |
| upper | 大文字 |
| lower | 小文字 |
| space | 空白類(スペース、タブ、改行など) |
| punct | 記号(英数字と空白以外の、印字できる文字) |
| xdigit | 16進数に使う文字(0〜9、a〜f、A〜F) |
このほかに、blank、cntrl、graph、print、ascii、word があります。
外側の [ ] が文字指定の角括弧で、内側の [: :] がクラス名の記法です。[:upper:] だけを書くと、:、u、p、e、r のどれか1文字を指定する意味になるので、[[:upper:]] と二重に書きます。
大文字(upper)
[[:upper:]]* は、先頭が大文字の名前に一致します。
[[:upper:]]* は大文字で始まる名前に一致するhirotano@linux-1:~$ echo [[:upper:]]*
Backup111 Backup222 Backup333 IMAGE IMAGE1 IMAGE12
小文字(lower)
*[[:lower:]] は、末尾が小文字の名前に一致します。
*[[:lower:]] は小文字で終わる名前に一致するhirotano@linux-1:~$ echo *[[:lower:]]
1-music 11-music 2-music file2.txt
数字(digit)
[[:digit:]]* は、先頭が数字の名前に一致します。
[[:digit:]]* は数字で始まる名前に一致するhirotano@linux-1:~$ echo [[:digit:]]*
1-music 11-music 2-music
まとめ
パス名展開では、*、?、[ ] を組み合わせて、名前のパターンを書きます。パターンはシェルが先に展開するので、コマンドには、一致した名前が並んで渡されます。今回の例を一覧にします。
| パターン | 一致する名前 | 例の結果 |
|---|---|---|
* | 任意の文字列(すべての名前) | 16個すべて |
d* | d で始まる | data1 data11 data111 dir1 dir11 |
*11 | 11 で終わる | Backup111 data11 data111 dir11 |
d*11 | d で始まり 11 で終わる | data11 data111 dir11 |
????? | 5文字 | IMAGE data1 dir11 file1 |
???11 | 任意の3文字のあとに 11 | dir11 |
f*.??? | f で始まり、拡張子が3文字 | file2.txt |
[ABC]* | A、B、C のどれかで始まる | Backup111 Backup222 Backup333 |
[a-f]* | a から f のどれかで始まる | data1 data11 data111 dir1 dir11 file1 file2.txt |
*[1-3][1-3][1-3] | 末尾が1から3の数字3つ | Backup111 Backup222 Backup333 data111 |
*[!1-3][1-3][1-3] | 末尾が「1〜3以外の1文字」+「1〜3の2文字」 | IMAGE12 data11 dir11 |
{file1,data*} | ブレース展開(先に展開される) | file1 data1 data11 data111 |
[[:upper:]]* | 大文字で始まる | Backup111 Backup222 Backup333 IMAGE IMAGE1 IMAGE12 |
*[[:lower:]] | 小文字で終わる | 1-music 11-music 2-music file2.txt |
[[:digit:]]* | 数字で始まる | 1-music 11-music 2-music |
思ったとおりに展開されないとき
| 状態 | よくある原因 | 確認すること |
|---|---|---|
| パターンがそのまま表示される | 一致する名前がない。または、パターンを引用符(' や ")で囲んでいる | ls で名前を確認する。引用符を外す。一致しないときに何も渡さない設定は shopt -s nullglob |
| . で始まる名前が出ない | * や ? は、先頭のピリオドに一致しない | .* のようにピリオドを書く。または shopt -s dotglob |
| 大文字小文字が一致しない | パス名展開は、大文字と小文字を区別する | 大文字小文字を区別しない設定は shopt -s nocaseglob |
[a-f] で想定外の名前が出る | 範囲が、ロケールの照合順で解釈されている | shopt globasciiranges を確認する。[[:lower:]] などの文字クラスを使う |
| サブディレクトリの中が出ない | * は / に一致しない | dir*/* のようにパスを区切って書く |
コメント