1

私はスクリプトを持っています:

#!/bin/bash
SINGLE_FILE=/tmp/blah.file
MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file

cp $SINGLE_FILE $MULTIPLE_FILES /tmp/newDir

これは次の場合に失敗します:

cp:統計できません `/tmp/{dir1,dir2}/*.file':そのようなファイルまたはディレクトリはありません

スクリプトが変数のワイルドカードを拡張していないようです。したがって、このスクリプトを次のように機能させることができます。

eval cp $SINGLE_FILE $MULTIPLE_FILES /tmp/newDir

私の質問は、スクリプトが最初に変数を展開しないのはなぜですか?また、使用する以外にこれを解決する別の方法はありevalますか?

4

3 に答える 3

3

スクリプト変数を、設定した値に展開しています/tmp/{dir1,dir2}/*.file

そして、あなたが正しく発見したように、シェルに「その行をもう一度実行する」ように依頼し、そこにある変数を再評価する必要があります。

したがって、eval 以外の方法はありません (サブシェル化して多くの処理能力を浪費し、本質的に eval の機能を独自のコードで作り直すことができます)。

私がお勧めできる唯一のことは、シェルのデバッグ機能を使用してset -vx、それがどのように機能しているかを自分で確認することです。

$set -vx
set -vx
>set -vx
$SINGLE_FILE=/tmp/blah.file
SINGLE_FILE=/tmp/blah.file
>SINGLE_FILE=/tmp/blah.file

$MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file
MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file
>MULTIPLE_FILES='/tmp/{dir1,dir2}/*.file'

$echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
>echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
/tmp/blah.file /tmp/{dir1,dir2}/*.file /tmp/newDir

$eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
>eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
echo /tmp/blah.file /tmp/{dir1,dir2}/*.file /tmp/newDir
>echo /tmp/blah.file '/tmp/dir1/*.file' '/tmp/dir2/*.file' /tmp/newDir
/tmp/blah.file /tmp/dir1/*.file /tmp/dir2/*.file /tmp/newDir
于 2011-10-13T15:45:12.127 に答える
2

ここで物事を混乱させているのは中括弧のようです。IMO、その不整合はシェルのバグです-もしあなたが持っていればMULTIPLE_FILES=/tmp/dir1/*.file、それはすぐにそれを拡大するでしょう。中かっこを追加すると、拡張の試行が停止します。他の何かを実行しているときはどちらが異なります。

それまでの間、evalはここでの悪い解決策/回避策ではありません。私が頭のてっぺんから考えることができる他の唯一のものは、であるでしょうMULTIPLE_FILES=$(echo /tmp/{dir1,dir2}/*.file)、それは必ずしもより良いとは限りません。

スペースがファイル/ディレクトリ名にある場合、適切なシェル解析は難しいため、一般的に、私はこのタイプのことを避けようとします。代わりに、find ... -print0 | xargs -0 ...できるだけ多く使用するようにしています。または、perlのような別のスクリプト言語に直接変換します。

于 2011-10-13T15:53:49.130 に答える
1

配列を使用できます:

SINGLE_FILE=/tmp/blah.file
MULTIPLE_FILES=( /tmp/{dir1,dir2}/*.file )
cp -t /tmp/newDir "$SINGLE_FILE" "${MULTIPLE_FILES[@]}"
于 2011-10-13T18:45:20.167 に答える