次のファイル(ワイルドカードまたはフォルダーを含むファイル)のリストを含む入力パラメーターがあります。
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
汚れた引用符を解析する場合は、出力にこの内容が表示されます)
実際、この割り当てでは、配列の使用のすべての利点が意味をなさなくなります。