bashの1つの変数だけで構成される引数のリスト

bashの1つの変数だけで構成される引数のリスト

次のファイル(ワイルドカードまたはフォルダーを含むファイル)のリストを含む入力パラメーターがあります。

list="file1 dir1 **.data **.source"

このリストの各要素にはプレフィックスを付け、次のように--filter=+ コマンド引数のリストに置き換える必要がありますrsync

args='--filter=="+ file1" --filter="+ dir1" --filter="+ **.data" --filter="+ **.source"'

だから通り過ぎると$パラメータ各引数を正しく受け取る必要がありますrsync $args。ここで、「+」内のスペースは、2つの引数の区切り文字ではなく、引数の1文字でなければなりません。

組み込みのシェルコマンドのみを使用して、シェルスクリプトでこれをどのように実行できますか?コマンドはrsync各パラメーターを正しく受信する必要があります。

失敗した試み:

#!/bin/bash
set -f
list="file1 dir1 **.data **.source"
ct=0
arr=""
for i in $list; do
    ct=$(( ct + 1 ))
    arr[$ct]="--filter='+ $i'"
done
args=${arr[*]}

set -x
echo args:$args
rsync $args srcdir destdir
set +x

実行すると(フォルダがsrcdir現在のディレクトリに存在すると仮定)、次のようになります。

$ ./test
+ echo args: '--filter='\''+' 'file1'\''' '--filter='\''+' 'dir1'\''' '--filter='\''+' '**.data'\''' '--filter='\''+' '**.source'\'''
args: --filter='+ file1' --filter='+ dir1' --filter='+ **.data' --filter='+ **.source'
+ rsync '--filter='\''+' 'file1'\''' '--filter='\''+' 'dir1'\''' '--filter='\''+' '**.data'\''' '--filter='\''+' '**.source'\''' a b
Unknown filter rule: `'+'
rsync error: syntax or usage error (code 1) at exclude.c(904) [client=3.1.1]
+ set +x

echo各パラメータが正しく表示されていることを確認してください。

args: --filter='+ file1' --filter='+ dir1' --filter='+ **.data' --filter='+ **.source'

rsync"+"は引数を完成し、スペースは引数の一部ではなく区切り文字であるため、すべての引数が削除されるため、コマンドは各引数を正しく理解しているようには見えません。

ベストアンサー1

ファイル名とパターンのリストを単一の文字列として使用する代わりに、それを配列で始めることができます。

list=(file1 dir1 "**.data" "**.source")

次に要素を繰り返します。

args=()
for item in "${list[@]}" ; do
    args+=(--filter="+ $item")
done

--filter=+ file1これにより、パラメータ文字列内に引用符なしで同様のパラメータが生成されます。 (引用符を入れたくありませんrsync。たとえば、引用符を含むフィルタルールについて文句を言いますrsync "--filter='+ foo'" ...。)

コマンドに配列を渡すときは、次のように"${args[@]}"配列要素を一意の文字列として渡す必要があります。

rsync "${args[@]}" "$srcdir" "$destdir"

代わりに"--filter=+ foo"使用できるようです--include=foo。これにより、パラメータから問題のあるスペースが削除されます(ただし、ファイル名パターンからスペースやワイルドカードは削除されません)。


あなたの場合は、set -fワイルドカードを無効にして動作for i in $listします。しかし、配列が必要なので、最初は配列を使用する方が良いでしょう。

さらに重要なことは、割り当てがargs=${arr[*]}配列を単一の文字列に平面化することです。引数内のスペースと引数の間のスペースは同じで、--filter=+ file1 --filter=+ dir1 ...シェルは異なるタイプのスペースを区別できません。引用符のない拡張は$argsすべての空白に分割されます(set -x汚れた引用符を解析する場合は、出力にこの内容が表示されます)

実際、この割り当てでは、配列の使用のすべての利点が意味をなさなくなります。

おすすめ記事