Rsync はスクリプト内の二重引用符を無視します

Rsync はスクリプト内の二重引用符を無視します

変数が"$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[@]}"

関連情報