理系学生日記

おまえはいつまで学生気分なのか

BashのGlobに関わるオプション

前に Bash の Glob に関するエントリを書きました。

他にも Glob には様々な応用があります。 あまり知られていないような使い方も多いので、それらをご紹介していくコーナーです。

extglob

Glob で正規表現と not 条件を表現できるようになる。 詳細については、

に書きました。

nullglob

通常、Glob を指定したもののそれが合致するファイル/ディレクトリが存在しない場合、Bash は指定した Glob をファイル名として解釈します。 何を言っているかというと、これを見れば分かって頂けるでしょうか。

# *.hoge というファイルが存在しないので、Bash は '*.hoge' というファイル名をそのままコマンドに渡す
$ ls *.hoge
ls: cannot access '*.hoge': No such file or directory

この挙動がどういうときに困るかというと…

#!/bin/bash

for f in *.hoge; do
    echo "file name is $f"
done

上記のようなスクリプトを走らせると、*.hoge に合致するファイルが存在しなかった結果、*.hoge というリテラルがそのまま echo に渡ってしまい、出力は file name is *.hoge になってしまいます。 *.hoge に合致するファイルが無いんであれば、単純にこの for ループは空回りして欲しいですよね。

そういうとき、shopt -s nullglob で nullglob オプションを有効化します。

#!/bin/bash

shopt -s nullglob

for f in *.hoge; do
    echo $f
done

nullglob は、「Glob に合致するファイル/ディレクトリが存在しない場合、Glob を空文字列に展開する」というオプションです。 この結果、上記の nullglob を有効化した for ループは空回りし、何も出力せずに終了させることができるようになります。

また、ls *.hoge を実行するしようとすると、*.hoge が空文字に展開されますので、ls が実行されることになります。

failglob

failglob は、指定した Glob を展開しようとしたときに合致するファイル/ディレクトリが存在しない場合、エラーとしてコマンド実行も実施しないというオプションです。 インタラクティブに bash を使う場合、typo とかにすぐ気付くことができます。

# failglob が無効になっている場合
$ ls *.hoge
ls: cannot access '*.hoge': No such file or directory

# failglob を有効化した場合、ls は実行されないことが分かる
$ shopt -s failglob
$ ls *.hoge
bash: no match: *.hoge

dotglob

Glob は、いわゆる隠しファイル (先頭が . から始まるファイル) には合致しないのがデフォルトの動作です。 実はこの挙動、dotglob オプションで変更することができます。

# こうやって隠しファイルを作っても、デフォルトの設定だと Glob に合致しない
$ touch .hiddenfile
$ ls *
test.txt

# dotglob を有効化すると合致するようになる
$ shopt -s dotglob
$ ls *
.hiddenfile  test.txt

隠しファイルを含めて処理をしたい時とかに使うと処理が楽になります。

shopt -s dotglob
for f in *; do
    echo $f   # 隠しファイルも含める
done