回答:
bashシェルのmanページから適応し、
bashは、*、?、および[の各文字をスキャンします。これらの文字のいずれかが表示される場合、その単語はパターンと見なされ、パターンに一致するファイル名のアルファベット順にソートされたリストに置き換えられます。一致するファイル名が見つからず、シェルオプションnullglobが有効になっていない場合、単語は変更されません。nullglobオプションが設定されていて、一致するものが見つからない場合、単語は削除されます。
この場合、nullglobが有効になっていないと想定しているため、単語は変更されないままなので、出力が表示されます。
出力が得られないと予想していました。
Ifはnullglob
デフォルトだった、(おそらく残念ながら)コマンドがある場合扱うのが一般的であるため、多くのコマンドは、全く予想外振る舞うゼロの場合よりも質的に異なる方法でファイル名の引数を一つ以上のファイル名の引数を指定します。
nullglob
(shopt -s nullglob
)を有効にし、一致するファイルがないディレクトリにいるとします*.txt
。その後、*.txt
実際には何も展開しません。空のフィールドではなく、フィールドはまったくありません。しかし、その結果は次のようになります。
ls *.txt
現在のディレクトリにあるすべてのファイル(隠しファイルを除く)を一覧表示しますls
。これは、ファイル名引数を渡さない場合に行われるためです。cat *.txt
がファイル名引数を持たない場合は、実行したかのように、標準入力から読み取りcat
ますcat -
。インタラクティブに実行している場合は、入力を待機しています。多くのコマンドはこのように動作します。cp *.txt dest/
エラーで失敗しますcp: missing destination file operand after 'dest/'
。これは災害ではありませんが、混乱を招き、おそらく望ましいサイレント成功とはかなり異なります。file *.txt
、およびファイル名引数がゼロの場合に特別な動作を行わない他のさまざまなプログラムは、何も渡されない場合でもエラーまたは使用法メッセージで失敗します。printf 'Got file: "%s"\n' *.txt
印刷するGot file: ""
代わりに印刷します。*
、?
とされていないシェルによって展開されることを意図し、より多くの場合、明らかに間違った結果を生むだろうが、把握するのが難しいかもしれない方法インチ たとえば、現在のディレクトリにで始まるファイル名がない場合、(意図されていた場所で)が正しくなり、使用可能なすべてのパッケージがリストされます。[
gedit
apt list gedit*
apt list 'gedit*'
apt list
したがって、要求しないとこの動作が発生しないのは良いことです。おそらく実際に単純化される最も一般的な実際の状況nullglob
はfor f in *.txt
です。この質問も参照してください(Sergiy Kolodyazhnyyの回答にリンクされています)。
答えるのが難しい質問は、failglob
どのファイルにも一致しないグロブがあると展開エラーになるのに、bashのデフォルトではない理由です。Sergiy Kolodyazhnyyの回答は、直接対処しなくても、この理由を捉えていると思います。展開エラーを生成せずに展開されていないグロブを保持することは、(おそらく残念なことに)標準化された動作であり、これも従来の動作であり、したがって期待される動作です。bashは、名前を指定して呼び出されるsh
か、--posix
オプションを渡さない限り、完全にPOSIXに準拠しようとはしませんが、POSIXモードでない場合でも、設計の選択肢の多くはPOSIXに直接従います。彼らはいくつかの行動を選ぶ必要があり、ユーザーの期待に反することに関連する欠点があります。
これは最も歴史的に影響の少ない問題だと思うので、最後に保存しておきますが、nullglob
動作については概念的に少し奇妙な点があることに言及する価値があります。
nullglob
構文的には、一致するファイルがゼロの場合も1、2、またはその他の数の場合と同じように扱われるため、最初はエレガントに見えます。上で詳述したように、グロブが引数に展開される、実行するコマンドは同じように処理する傾向はありません。しかし、構文的にはこれは少なくとも正しいと感じます。これがあなたの質問の動機だと思います。
それでも、nullglob
対処できない別のより微妙な不整合があります-それは実際に増幅します。ゼロのグロビング文字(「ワイルドカード」)の場合は、1つ、2つ、またはその他の数字の場合とは大きく異なります。たとえば、ではshopt -s nullglob
、ab?d?f
どのファイルとも一致しない場合は削除されます。ab?d
どのファイルとも一致しない場合は削除されます。ただし、ab
どのファイルとも一致しない場合(つまり、名前が正確にのファイルがない場合ab
)は、削除されません。もちろん、現在のディレクトリにある既存のファイルを参照することをまったく意図していない可能性があるため、削除した場合は問題になります。ファイルを参照しないこともあります。しかし、これはまだ完全な一貫性への希望を排除します。
bashが提供する3つの動作-ファイルに一致しないグロブをグロブではないかのように扱い、展開せずに渡すデフォルト、それらを処理することで期待される動作(この奇妙なフレーズのターンを許す場合)一致するファイルのすべてのゼロ(nullglob
)と、それらをエラーと見なす安全な動作()を意味します。これらはfailglob
すべて、特定の単語がファイル名。シェルは、それを使用して呼び出す特定のコマンドが引数をどのように処理するかを認識せずに、展開を実行します。
これは、懸念の分離の多くの例の1つです。Unixの哲学に従って設計されたシステムでは、各部分は1つのことを行い、それをうまく行うことを目的としています。シェルはテキストをコマンドと引数に処理し、それらのコマンドを呼び出します。これらのコマンドのほとんどはシェル自体の外部にあります。これは、外部コマンド自体が(DOSやWindowsの従来のコマンドプロセッサのように)これらの変換を実行する責任があるシステムよりも優れており、用途が広い傾向があります。しかし、それはその時々の欠点があります。
failglob
。したがって、常にサポートされているわけではないため、デフォルトにすることはできません。
主な理由は、これがPOSIXによって指定された標準の動作であり、シェルコマンド言語やその他のパターンマッチング(シェルbash
、dash
Ubuntuのデフォルトなどのシェル/bin/sh
、およびksh
この標準に従う)をカバーする標準だからです。セクション2.13.3から、ファイル名拡張に使用されるパターン:
パターンが既存のファイル名またはパス名と一致しない場合、パターン文字列は変更されません。
もちろん、これには文字通りの副作用と一致するファイル名があります*.txt
。nullglob
内のオプションbash
とzsh
缶ヘルプ:そのオプションを経由して有効になっている場合shopt -s nullglob
(そしてそれはこの質問に適用され、デフォルトでは有効になっていません)、一致するファイル名が見つからないときにglobstar空の文字列に展開されます。ksh93
同じ効果を実現する独自の高度なパターンマッチングメカニズム~(N)*.txt
nullglobがデフォルトではない理由も参照してください。
shopt -s nullglob
一致しないパターンに対して空の文字列を生成し、shopt -u nullglob
(標準設定)はパターン自体を生成します。