ワイルドカードと中括弧内に指定された拡張子セットを含む文字列を拡張しようとしています。以下の例に示すように、何の効果もないようです。変数はfirstList
うまく拡張されますが、secondList
またはは正しく拡張されthirdList
ませんfourthList
。私もさまざまなバージョンを試しましたが、eval
そのうちの何も動作しません。どんな助けでも大変感謝します。
#!/bin/bash
touch a.ext1
touch b.ext1
firstList='*.ext1'
ls $firstList
touch a.ext2
touch b.ext2
secondList='*.{ext1,ext2}'
ls $secondList
ls '$secondList'
ls "$secondList"
thirdList=*.{ext1,ext2}
ls $thirdList
ls '$thirdList'
ls "$thirdList"
fourthList="*.{ext1,ext2}"
ls $fourthList
ls '$fourthList'
ls "$fourthList"
答え1
これシェル拡張は引用されていない場合にのみ発生します*
。引用すると、シェルは拡張されません。
また、シェルから拡張するには、中かっこ拡張を引用符解除する必要があります。
これはうまくいきます(Echoを使ってシェルが何をしているのか見てみましょう)。
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
別の名前のファイルが存在する場合でも:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
これがうまくいくのはなぜですか?
それがなぜ機能するのかを理解することが重要です。これは拡張順序によるものです。最初に「中括弧拡張」があり、最後に「パス名拡張」(別名glob拡張)があります。
Brace --> Parameter (variable) --> Pathname
「パス名の拡張」を一時的にオフにできます。
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
「パス名の拡張」は、と*.ext1
の2つのパラメータを使用します*.ext2
。
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
問題は、変数を使用して中括弧拡張を実行できないことです。
これは以前にも何度も説明しました。「分岐拡張」で変数を使用する
「変数拡張」の結果である「中括弧拡張」を拡張するには、コマンドラインをシェルに再送信する必要がありますeval
。
$ list={ext1,ext2}
$ eval echo '*.'"$list"
サポート -->変える-->グローバル|-->サポートする-->変数-->全体的な状況
........ここに引用-->^^^^^^ ||評価^^^^^^^^^^^^^^^^^^^^^^^^^^
ファイル名の値は評価実行の問題を引き起こしません。
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
しかし、その価値は$list
安全ではないかもしれません。ただし、値は$list
スクリプト作成者によって設定されます。スクリプト作成者は以下を制御できますeval
。外部で設定された値を使用しないだけです$list
。この試み:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
より良い選択。
(評価なし)別のオプションは次のとおりです。Bash「拡張モード」を使う:
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
注:2つのソリューション(評価とパターン)(作成したとおり)は、スペースや改行を含むファイル名に対して安全です。ただし、引用符がないか、evalが引用符を削除する$list
ため、空白がある場合は失敗します。$list
答え2
考慮する:
secondList='*.{ext1,ext2}'
ls $secondList
問題は支柱の拡張もう終わった今後 変数拡張。これは、上記の場合、支柱の拡張が行われないことを意味します。
これは、bashがコマンドラインを最初に見たときに中括弧がないためです。拡張後secondList
は遅すぎます。
以下が機能します。
$ s='*'
$ ls $s.{ext1,ext2}
a.ext1 a.ext2 b.ext1 b.ext2
ここで、コマンドラインには次のように中括弧があります。支柱の拡張最初のステップとして実行できます。その後、$s
(の値を置き換えます。変数拡張)ついにパス名拡張処刑される。
文書
man bash
拡張順序を説明してください。
拡張順序は、中かっこ拡張、パラメータと変数拡張、算術拡張、コマンドの置換(左から右へ)です。