この小さな設定は私を夢中にさせました:
shopt -s nullglob
私はbash4.3スクリプトでそれをグローバル設定として使用します 空のディレクトリのスキャンエラーを回避します 。
今、私は理解できない奇妙な問題を見つけました:
# shopt -s nullglob
# array=(foo bar)
# echo "${array[@]}"
foo bar
# array=(foo bar?)
# echo "${array[@]}"
foo
# shopt -u nullglob
# array=(foo bar)
# echo "${array[@]}"
foo bar
# array=(foo bar?)
# echo "${array[@]}"
foo bar?
ご覧のとおり、配列要素からbar?
が削除されますが、なぜですか? documentation は、*
と?
を含む可能性のあるファイル名パターンを指しますが、配列だけでは「ファイルが一致しない」とは関係ありません。
If set, Bash allows filename patterns which match no files to expand to a null string, rather than themselves.
これはバグですか?
P.S.問題を解決するために、ループの周りにnullglobを設定/設定解除します。これは問題ではありません!
Update1
@MichaelHomerが求めたように:
# shopt -s nullglob
# array=(*)
# echo "${array[@]}"
1 Video_folder Server bin config dev etc etc.defaults initrd lib lib32 lib64 lost+found mnt proc root run sbin storage sys tmp tmpRoot usr var var.defaults volume1
# shopt -u nullglob
# array=(*)
# echo "${array[@]}"
1 Video_folder Server bin config dev etc etc.defaults initrd lib lib32 lib64 lost+found mnt proc root run sbin storage sys tmp tmpRoot usr var var.defaults volume1
そしてこれはどういう意味ですか?
array=(foo bar?)
を実行すると、_bar?
_文字列は引用符で囲まれず、ファイル名グロブ文字_?
_(任意の1文字に一致)が含まれます。これは、シェルがこの値に対してファイル名のグロブを実行することを意味します。パターンが何にも一致しない場合、デフォルトではそのままになります。何か(_bar1
_、_bar-
_、_bar.
_など)と一致する場合、一致する名前が配列に挿入されます。
nullglob
を有効にすると、引用符で囲まれていないグロブパターン_bar?
_は、それに一致するファイル名がない場合は完全に削除されます(これが、通常、nullglob
を有効にする理由です)。これは、この場合、配列にはfoo
要素のみが含まれることを意味します。
言い換えると、nullglob
設定は(現在のディレクトリに_bar?
_というファイルがない限り)引用符で囲まれていないWord _bar?
_が配列の要素として割り当てられるのを防ぎます。
配列に2つの文字列foo
と_bar?
_が必要な場合の解決策は、それらを引用符で囲むことです(foo
は引用符で囲む必要はありませんが、一貫性を保つのに問題はありません)。 :
_array=('foo' 'bar?')
_
これを「解決」する別の方法は、disableファイル名のグロブです。これは_set -f
_を介して行われます:
_set -f
array=(foo bar?)
set +f
_
Michaelがおそらくarray=(*)
で示したかったのは、引用符で囲まれていない値(ここでは引用符で囲まれていない_*
_)に対してグロブが発生することです。これがあなたの問題の根源であるため、彼はこれを示したかったのです。