web-dev-qa-db-ja.com

変数でワイルドカードをbashに展開させる方法は?

タイピングと同じ効果を得ようとしています

mv ./images/*.{pdf,eps,jpg,svg} ./images/junk/  

コマンドラインで、bashスクリプト内から。私が持っています:

MYDIR="./images"
OTHERDIR="./images/junk"  
SUFFIXES='{pdf,eps,jpg,svg}'
mv "$MYDIR/"*.$SUFFIXES "$OTHERDIR/"

これを実行すると、予期しないエラーは発生しません。

mv: rename ./images/*.{pdf,eps,jpg,svg} to ./images/junk/*.{pdf,eps,jpg,svg}: 
No such file or directory

mvが実際に目的の展開を行うために、これらすべてを引用する正しい方法は何ですか? (はい、./images/のパターンに一致するファイルがたくさんあります。)

29
Ross Duncan

削除された回答は正しい軌道に乗っていました。あなたの試みを少し変更します:

shopt -s extglob
MYDIR="./images"
OTHERDIR="./images/junk"  
SUFFIXES='@(pdf|eps|jpg|svg)'
mv "$MYDIR/"*.$SUFFIXES "$OTHERDIR/"

ブレース展開は変数展開の前に行われますが、変数展開はパス名展開の前に行われます。したがって、元の変数が展開された場合でも中括弧は中括弧になりますが、変数にパス名要素が含まれている場合は、パス名の展開が行われたときに既に展開されています。

29

次のように機能するためには、その行を評価する必要があります。

MYDIR="./images"
OTHERDIR="./images/junk"  
SUFFIXES='{pdf,eps,jpg,svg}'
eval "mv \"$MYDIR\"/*.$SUFFIXES \"$OTHERDIR/\""

さて、これは特に信頼できない場合、特に問題があります$SUFFIXES、インジェクション攻撃が含まれている可能性がありますが、この単純なケースでは問題ありません。

他のソリューションを利用できる場合は、findxargsを試してみてください。

8
falstro

あなたは関数を書くことができます:

function expand { for arg in "$@"; do [[ -f $arg ]] && echo $arg; done }

次に、拡張したいものでそれを呼び出します:

expand "$MYDIR/"*.$SUFFIXES

必要に応じて、スクリプトをexpand.shにすることもできます。

0
Dagang