ほとんどのシェルではnullglob
デフォルトではありません。つまり、たとえば、このコマンドを実行した場合
ls *
空のディレクトリでは、 *
が展開されます リテラル*
へのグロブ 、代わりに引数の空のリストに。 *
となるように、その動作を変更する方法があります。 空のディレクトリにあると、引数の空のリストが返されます。これは、より直感的に見えるでしょう。
それで、 nullglob
が理由があります デフォルトでは無効になっていますか?もしそうなら、その理由は何ですか?
承認された回答:
nullglob
オプション(ところで、これは zsh
発明、数年後に bash
に追加されました ( 2.0
))多くの場合、理想的ではありません。そしてls
良い例です:
ls *.txt
または、より正確な同等物:
ls -- *.txt
nullglob
を使用 onはls
を実行します ls-。
として扱われる引数なし (現在のディレクトリをリストします)一致するファイルがない場合、これはおそらく ls
を呼び出すよりも悪いです リテラルの*。txt
を使用 引数として。
ほとんどのテキストユーティリティでも同様の問題が発生します:
grep foo *.txt
foo
を探します txt
がない場合はstdinに ファイル。
より賢明なデフォルトであり、csh、tcsh、zsh、またはfish 2.3以降(および初期のUnixシェル)の1つは、globが一致しない場合にコマンドを完全にキャンセルすることです。
bash
(バージョン3以降)には failglob
があります そのためのオプション( ash
とは対照的に、この議論に興味があります 、AT&T ksh
またはzsh
、 bash
オプションのローカルスコープをサポートしていません(ただし、4.4で変更されます)。グローバルに有効にすると、そのオプションはbash-completion関数などのいくつかの機能を壊します。
cshとtcshはzsh
とは少し異なることに注意してください 、 fish
またはbash-O failglob
次のような場合:
ls -- *.txt *.html
コマンドをキャンセルするために、すべてのグロブを一致させないようにする必要がある場合。たとえば、txtファイルが1つあり、htmlファイルがない場合、次のようになります。
ls -- file.txt
zsh
でその動作を得ることができます setopt cshnullglob
を使用 zsh
でそれを行うためのより賢明な方法ですが 次のようなグロブを使用することになります:
ls -- *.(txt|html)
zsh
で およびksh93
、 nullglobを適用することもできます グロブごとに、これはグローバル設定を変更するよりもはるかに賢明なアプローチです:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
txt
がない場合は、空の配列が作成されます コマンドをエラーで失敗させる(または1つの*。txt
を含む配列にする)代わりにファイル 他のシェルとのリテラル引数)。
fish
のバージョン 2.3より前のバージョンはbash-O nullglob
のように機能します ただし、グロブに一致するものがない場合、インタラクティブのときに警告を出します。 2.3以降、 zsh
のように機能します for
で使用されるグロブを除く 、 set
またはcount
。
さて、履歴ノートでは、動作は実際には壊れていました ボーンシェルによって。 Unixの以前のバージョンでは、グロブは / etc / glob
を介して行われました。 ヘルパーとそのヘルパーはcsh
のように動作しました :どのグロブもどのファイルにも一致しない場合はコマンドに失敗し、それ以外の場合は一致しないグロブを削除します。
したがって、今日の状況は、Bourneシェルで行われた誤った決定によるものです。
Bourneシェル(およびCシェル)には、別の新しいUnix機能である環境が付属していることに注意してください。これは可変拡張を意味しました(前任者には $ 1
しかありませんでした 、 $ 2
…位置パラメータ)。 Bourneシェルもコマンド置換を導入しました。
Bourneシェルのもう1つの不十分な設計上の決定は、変数の展開とコマンド置換の際にグロブ(および分割)を実行することでした(おそらく、 echo $ 1
であるThompsonシェルとの下位互換性のためです。 それでも/etc / glob
を呼び出します $ 1
の場合 ワイルドカードが含まれていました(展開された値がシェルコードとして再度解析されたため、プリプロセッサマクロの展開に似ていました)。
一致しないグロブが失敗すると、たとえば次のようになります。
pattern='a.*b'
grep $pattern file
コマンドが失敗します( a.whateverb
がない場合 現在のディレクトリ内のファイル)。 csh
(変数の展開時にグロビングも実行します)その場合、コマンドは失敗します( zsh <のようにグロビングをまったく行わないほど良くない場合でも、休止状態のバグを残すよりはましだと思います。 / code> 。