![Rsync はスクリプト内の二重引用符を無視します](https://rvso.com/image/1684445/Rsync%20%E3%81%AF%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E5%86%85%E3%81%AE%E4%BA%8C%E9%87%8D%E5%BC%95%E7%94%A8%E7%AC%A6%E3%82%92%E7%84%A1%E8%A6%96%E3%81%97%E3%81%BE%E3%81%99.png)
変数が"$exclude_list"
パラメータとして呼び出されると、rsync は二重引用符を無視し、スクリプトに記載されていないホーム フォルダも何らかの方法で含めます。 で囲もうとしましたが"${exclude_list}"
、それでも効果はありませんでした。
と組み合わせて使用する前に変数の内容を表示するとrsync
、それが正しいことがわかります。
もう一つの奇妙な点は、実行するとecho rsync ...
出力が正しく、エラーがないことです。
問題のある bash スクリプトの一部:
echo "$exclude_list"
rsync -av --dry-run "$exclude_list" "$src" "$dest" >> /var/log/rsync.log || {
sendmail "Error: rsync failed for folder $src."; exit 1; }
出力:
--exclude=lost+found
rsync: [sender] link_stat "/home/user/ --exclude=lost+found" failed: No such file or
directory (2)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at
main.c(1333) [sender=3.2.3]
MCVE は次のとおりです。
#!/bin/bash
# List of source folders
SRC_FOLDERS=(
[0]="/mnt/load-1/"
[1]="/mnt/load-2/"
)
# List of backup folders
DEST_FOLDERS=(
[0]="/mnt/load-1-b/"
[1]="/mnt/load-2-b/"
)
# List of folders to exclude during backup
EXCLUDE_FOLDERS=(
"lost+found"
"lost-found"
)
# Form the exclude list for rsync
for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
exclude_list="$exclude_list --exclude=$exclude_folder"
done
# Loop through each folder pair
for i in "${!SRC_FOLDERS[@]}"; do
src=${SRC_FOLDERS[$i]}
dest=${DEST_FOLDERS[$i]}
rsync -av --dry-run "$exclude_list" "$src" "$dest"
done
答え1
問題は
for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do exclude_list="$exclude_list --exclude=$exclude_folder" done
配列を反復処理しEXCLUDE_FOLDERS
、そこから非配列変数を作成しますexclude_list
。後で として参照されると"$exclude_list"
、シェルはそれを 1 つの単語に展開します。
for
ループの前はexclude_list
空です。ループ内の最初の代入により、変数は で始まります--exclude…
。先頭のスペースに注意してください。このスペースがあるため、rsync
この単語はオプションとして認識されず、相対パス現在の作業ディレクトリは だと思います/home/user/
。絶対パスは なので/home/user/ --exclude=…
、そのようなファイルは存在しません、これがエラーの内容です。
先頭のスペースが存在せず、exclude_list
何らかの方法で として作成されたとしても--exclude=… --exclude=…
、それは間違いです。"$exclude_list"
は常に 1 つの単語に展開されます。 それぞれを--exclude=…
の別々の引数にする必要がありますrsync
。
引用符を付けないのも$exclude_list
、まあまあ使えるかもしれないが、あまり良い解決策ではない。例えばEXCLUDE_FOLDERS
要素にスペース、タブ、改行(またはグロブをトリガーするワイルドカード)が含まれている場合は失敗する可能性があります。。
読んでください変数に保存されたコマンドを実行するにはどうすればよいですか?Bash では、配列を使用するのが最適な場合がよくあります。exclude_list
配列を作成します。
for exclude_folder in "${EXCLUDE_FOLDERS[@]}"; do
exclude_list+=("--exclude=$exclude_folder")
done
次に、 の呼び出しで をrsync
使用します"${exclude_list[@]}"
。