これはほとんどのシェルではnullglob
デフォルト設定ではありません。これは、たとえば、このコマンドを実行した場合
ls *
空のディレクトリでは、空の引数リストの代わりに*
globをテキストに展開します。空のパラメータリストが空のディレクトリに返される*
ように、この動作を変更する方法があります。これはより直感的に見えます。*
nullglob
それでは、デフォルトで無効になっている理由はありますか?では、なぜそうなのでしょうか?
答え1
nullglob
ほとんどの場合、このオプションは理想的ではありません。ls
良い例は次のとおりです。
ls *.txt
または、より正確な表現は次のとおりです。
ls -- *.txt
.txt
(タイプを除く名前が次に終わるファイルのリスト)目次-d
その内容がリストされています。おそらく、特別な扱いを避けるためにこのオプションを使用しようとします。目次文書)。
一致するファイルがない場合、onはnullglob
引数なしで実行され、これは(現在のディレクトリの内容の一覧表示)ls
として扱われ、これはリテラルを引数として呼び出すよりも悪い可能性があります。ls -- .
ls
*.txt
ほとんどのテキストユーティリティにも同様の問題があります。
grep foo *.txt
foo
ファイルが存在しない場合は、標準入力で検索が実行されますtxt
。
csh、tcsh、zsh、またはFish 2.3 +(および以前のUnixシェル)のデフォルト値であるより合理的なデフォルト値は、globが一致しない場合はコマンドを完全にキャンセルすることです。
bash
(バージョン3以降)オプションがありますfailglob
(この議論は、ash
AT&Tとは異なり、ksh
またはオプションのローカルスコープをサポートしていzsh
ないbash
3とは異なり、グローバルに有効にすると、bash-completion機能などの一部の機能が中断されるため興味深いものです)。
zsh
cshとtcshは、次の場合とはfish
若干異なります。bash -O failglob
ls -- *.txt *.html
コマンドを取り消すには、すべてのグローバル変数が一致しないようにしてください。たとえば、txtファイルはありますが、htmlファイルがない場合は次のようになります。
ls -- file.txt
with を使用してこの動作を取得できますが、zsh
よりset -o cshnullglob
合理的なアプローチzsh
は、次のようなglobを使用することです。
ls -- *.(txt|html)
とzsh
でもksh93
申請できます。空のボールグローバルごとに見ると、これはグローバル設定を変更するよりも合理的なアプローチです。
files=( *.txt(N) ) # zsh
files=( ~(N)*.txt ) # ksh93
ファイルが存在しない場合、txt
エラーのためにコマンドが失敗するのではなく空の配列が生成されます(または*.txt
別のシェルを使用して1つのリテラル引数を持つ配列にします)。
fish
2.3以前のバージョンも同様に機能していましたが、bash -O nullglob
対話中にglobが一致しない場合は警告が表示されました。 2.3 以降は、zsh
または で使用された glob とは異なって動作します。for
set
count
歴史的に、これらの行動は実際に壊れたBourne シェルとして実装されます。以前のバージョンのUnixでは、ワイルドカードの割り当ては次のよう/etc/glob
に機能するヘルパーを介して行われましたcsh
。ファイルに一致するワイルドカードがないとコマンドは失敗し、そうでないと一致するワイルドカードは削除されません。
したがって、今日私たちが持っている状況は、Bourneシェルから下された誤った決定によるものです。
Bourneシェル(およびCシェル)には、別の新しいUnix機能である環境が付属しています。これは変数拡張を意味します (以前のバージョンには$1
、$2
... 位置引数だけありました)。 Bourne シェルにはコマンド置換も導入されました。
Bourneシェルのもう1つの誤った設計決定は、変数の拡張とコマンドの置き換えにワイルドカード(および分割)を実行することです(おそらくワイルドカードが含まれている場合はまだ呼び出されるThompsonシェルとの下位互換性のため)echo $1
(プリプロセッサマクロと似ています)拡張)拡張値は再びシェルコードに解析されるため))。/etc/glob
$1
たとえば、一致しない失敗したglobは、次のことを意味します。
pattern='a.*b'
grep $pattern file
コマンドが失敗します(a.whateverb
現在のディレクトリにいくつかのファイルがない場合)。 (変数拡張時にもワイルドカードを実行します。)この場合、コマンドは失敗します。 ( //csh
のようにワイルドカードをまったく使用しないほど良くなくても休眠エラーをそのままにするよりは良いと思います。 .. )。rc
zsh
fish
shopt
組み込み機能は1996年2.0に追加され、zsh
そのオプションbash
にちなんで命名されました。allow_null_glob_expansion
変える以前のバージョンの場合
²その間隔内にファイルが作成されていないか、現在のディレクトリが検索可能であるが読み取れず、ファイルまたはディレクトリが存在しない限り、ファイルなしエラーが報告されることがls
あります。たとえば、試した後*.txt
mkdir -p '*.txt/wtf'; chmod a=,u=wx .
set -o
3バージョン4.4では、Almquistシェルと同様にオプションセットをローカル関数に設定できますが、2番目のオプションセット(オプションセットを含む)では機能しlocal -
ないため、これにはいくつかの改善がありました。bash
shopt
答え2
nullglob
この設計は、voidパラメータが指定されたときにvoid結果を生成するコマンドに対するデフォルト値の使用を考慮して、安全なアプローチをとります。ただし、このデフォルトの動作は、次のコマンドには適していない可能性がありますls
。スクリプトでは役に立ちますが、次の関数で置き換えないnullglob
限り、完全に安全ではありません。ls
myls() { (($#)) && ls "$@" ; }
これにより、nullglobを使用するときに目的の結果を得ることができます。
shopt -s nullglob
myls empty_directory/*
言語のデフォルトを設計する際の優先順位は、予期しない動作を最小限に抑えるオプションを採用することです。予測できない動作よりも例外を好みます。
nullglob
予測不能な入力変更を含む複雑なスクリプトを導入すると、スクリプトが不安定になる可能性があることに注意することが重要です。実際、これは良いアイデアと見なすことができますが、実際には予防デバッグには追加の時間が必要です。