シェルスクリプト:内部にオプションがある変数を作成する


11

次のパラメーターを指定したrsyncコマンドがあります。

rsync -avz --{partial,stats,delete,exclude=".*"}

そのパラメーターを変数内に配置して、スクリプトで後で再利用したいと考えています。このようなもの:

#!/bin/bash
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}
$VAR /dir1 /dir2

引用符、単一引用符、角かっこで試したが、成功しなかった。



以前にこの経路をたどっていた場合:最終的に得られるコマンド文字列に空の文字列が含まれていないことを確認してください。その場合、rsyncはそれらをパラメーターとして使用する可能性があり、それらは非表示であるため、デバッグがかなり困難です。私は空の最初のパラメーターを持っていて、rsyncはそれをコピーするもののソースに現在のディレクトリを含むものとして解釈しました。
Joe

回答:


12

複雑なコマンドを変数に入れることは決して推奨されるアプローチではありません。BashFAQ / 050を参照してください-コマンドを変数に入れようとしていますが、複雑なケースは常に失敗します!

変数の代わりに関数を使用して引数を渡すことにした場合、要件は非常に単純になります。

何かのようなもの

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --{partial,stats,delete,exclude=".*"} "$@"
}

そして必要な引数を次のように渡します

rsync_custom /dir1 /dir2

関数の定義はある意味で非常に単純です。最初に、$#ゼロであってはならない変数を使用して入力引数の数を確認します。引数が指定されていないというエラーメッセージをスローします。有効な引数がある場合"$@"、関数に提供される実際の引数を表します。

これはあなたがまた、スクリプト/コマンドラインで、すなわちかなり頻繁に使用されるだろう機能である場合は、シェルのスタートアップ・ファイルに追加し.bashrc.bash_profileインスタンスのために。

または、前述のように、読みやすくするために、中かっこを展開して引数を分離することは価値があります。

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --partial --stats --delete --exclude=".*" "$@"
}

5
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

これは、コマンドを実行しようと-avz引数を持つ--partial--statsなど。ととVARのセットrsync環境インチ

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

中かっこは引用符内で展開されておらず、代入内でも展開されておらず、変数が展開された後も展開されないため、引用フォームは機能しません。

コマンドライン引数を変数に格納する必要がある場合は、配列を使用します。

args=(rsync -avz --{partial,stats,delete,exclude=".*"})

今すぐ"${args[@]}"に拡大するrsync-avz--partial明確な言葉として、など。

配列を使用すると、必要に応じて条件に応じてリストにオプションを追加することもできます。たとえば、次のようにできます。

args=(this that)
if something ; then
    args+=(another_arg)
fi
"$cmd" "${args[@]}"

1

少なくとも、オプションを部分的に変数に保存できます。

opts=$(echo --{ignore-case,word-regexp,count,exclude='"sys*.*"'})

マスキングは困難な場合があるため、テストは重要です。

echo $opts
--ignore-case --word-regexp --count --exclude="sys*"

grep $opts bytes *.log 

履歴の使用、エイリアスの使用、関数の使用など、複数の選択肢があるため、私が考えることができる明らかなユースケースはありません。異なるプログラム間で共有する複雑なオプションはめったにありません。そのため、インタラクティブシェルのアドホックソリューションでは、エイリアスはより良い方法のように見えます。

alias cgrep='grep --ignore-case --word-regexp --count --exclude="sys*"'
cgrep bytes *.log

あなたのサンプル

VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

割り当てが最初の空白で終了しているため、機能しません。ブランクをマスクする必要があります:

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

--deleteオプションを使用してテストするのはかなり危険ですよね。オプションには "、"と一重引用符を含めることができるため、マスキングはすぐに難しくなる可能性があります。私はエイリアスに行くか、歴史に依存します。

〜/ .bashrcファイルにエイリアスを保存して、複数のセッションで継続的に使用できます。関数はbashrcにも格納できますが、パラメーターを処理する場合は、関数に渡されてそこで評価されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.