zshで変数を拡張する

zshで変数を拡張する

以下のスクリプトはbashでは機能しますが、zshでは機能しません。私はこれが変数内でOPTS変数を「拡張」(正しい単語かどうかわからない)していて、この構文が$EXCLUDEzshでは機能しないためだと思います。 zshで動作するようにこの行をどのように変更できますか?

SRC="/path_to_source"
DST="/path_to_dest"
EXCLUDE=".hg"  
OPTS="-avr --delete --progress --exclude=${EXCLUDE} --delete-excluded"                                               

rsync $OPTS $SRC $DST   

答え1

ここでの問題は、$OPTSコマンドラインで複数のパラメータに区別されないことですrsynczsh構文では、次を使用します。

rsync ${=OPTS} $SRC $DST 

(代替は、オプションを使用してグローバルに標準シェル動作をエミュレートすることです-o shwordsplit...)

マンページから:

[in]の一般的な違いzshは、コマンドラインで置き換えられた変数が単語に分割されないことです。SH_WORD_SPLIT「パラメータ拡張」セクションのシェルオプションの説明を参照してくださいzshexpn(1)。では、zsh明示的に分割を要求したり(たとえば${=foo})、変数を複数の単語に拡張したい場合は、配列を使用できます。の「配列パラメータ」を参照してください zshparam(1)

答え2

問題は、では$EXCLUDEなくで発生します$OPTS。あなたのスクリプトは単語分離の発生に依存します$OPTS。たとえば、現在のディレクトリに$EXCLUDEパターンと一致ファイルを含めるように変更したり、スペースを含めるように変更すると--exclude=$EXCLUDE失敗$EXCLUDEします。

$OPTS単一の単語ではなく単語のリストです。 ksh、bash、zshでのみ動作するスクリプトが必要な場合は、それを配列にします。

SRC="/path_to_source"
DST="/path_to_dest"
EXCLUDE=".hg"
OPTS=(-avr --delete --progress --exclude="$EXCLUDE" --delete-excluded)
rsync "${OPTS[@]}" "$SRC" "$DST"

スクリプトがzshでのみ機能するようにするには、最後の行を単純化するだけです。

rsync $OPTS $SRC $DST

すべてのシェルでスクリプトを実行するには、位置パラメータを使用する必要があります。これは利用可能な唯一の配列です。

set -- -avr --delete --progress --exclude="$EXCLUDE" --delete-excluded
rsync "$@" "$SRC" "$DST"

zshを使用してシェルスクリプトを簡単に実行するには、この行を先頭に配置します。これはzshがkshのように動作し、他のシェルでは何もしないように指示します。

emulate ksh >/dev/null 2>/dev/null || true

答え3

zshStéphane Gimenezの答えを完了するには(まだコメントできません)、1つの解決策はスクリプトを使用していることを$OPTS確認してから、次の配列に変換してスクリプトをbashに移植可能にすることです。

[ -n "${ZSH_VERSION:-}" ] && set -A OPTS ${=OPTS}

これで rsync コマンドが動作します。

関連情報