Bash

rsync 從 $@ 傳遞多個排除

  • August 31, 2022

我正在嘗試圍繞我的 rsync 命令製作一個包裝器以重用程式碼。我需要傳遞源文件夾、目標文件夾,然後是任意數量的排除目錄。這是我的日誌;基本上我正在從我的“vararg”參數中建構我的多個 rsync 的 –exclude 參數。可能有更好的方法,但我發現一個足夠好了。

function run_backup(){
   source="$1"
   target="/backups/unraid$2"
   #Copying $source into remote folder $target

   # Building my exclude params
   if [ $# -ge 3 ]; then
       excludes="--exclude '$3'"
       while shift && [ -n "$3" ]; do
           echo $excludes
           excludes="${excludes} --exclude '$3'"
       done
   else
       excludes = "--exclude '/tmp'" # Dummy exclude; I'll handle this case later
   fi
   echo $excludes
   
   # Creating folder because rsync crash otherwise n some case
   ssh -p 22 -i /home/backup/.ssh/mykey unraid@94.23.49.55 "mkdir -p $target"

   # Executing the copy
   set -e
   sudo rsync -azvh \
       -e "ssh  -p 22-i /home/backup/.ssh/mykey "\
       --progress \
       --delete \
       $excludes \
       $source \
       unraid@69.69.69.69:$target
}


mkdir -p /tmp/dummy
echo "dummy" > /tmp/dummy/save-ignored-1
echo "dummy" > /tmp/dummy/save-ignored-2
echo "dummy" > /tmp/dummy/save-test
run_backup /tmp/dummy/ /dummy /tmp/dummy/save-ignored-1 /tmp/dummy/save-ignored-2 /tmp/toto /tmp/tata /tmp/tutu #TODO
--exclude '/tmp/dummy/save-ignored-1'
--exclude '/tmp/dummy/save-ignored-1' --exclude '/tmp/dummy/save-ignored-2'
--exclude '/tmp/dummy/save-ignored-1' --exclude '/tmp/dummy/save-ignored-2' --exclude '/tmp/toto'
--exclude '/tmp/dummy/save-ignored-1' --exclude '/tmp/dummy/save-ignored-2' --exclude '/tmp/toto' --exclude '/tmp/tata'
--exclude '/tmp/dummy/save-ignored-1' --exclude '/tmp/dummy/save-ignored-2' --exclude '/tmp/toto' --exclude '/tmp/tata' --exclude '/tmp/tutu'
++ ssh -p 22-i /home/backup/.ssh/mykey unraid@69.69.69.69 'mkdir -p /backups/unraid/dummy'
++ sudo rsync -azvh -e 'ssh  -p 22 -i /home/backup/.ssh/mykey' --progress --delete --exclude ''\''/tmp/dummy/save-ignored-1'\''' --exclude ''\''/tmp/dummy/save-ignored-2'\''' --exclude ''\''/tmp/toto'\''' --exclude ''\''/tmp/tata'\''' --exclude ''\''/tmp/tutu'\''' /tmp/dummy/ unraid@94.23.49.55:/backups/unraid/dummy

我們可以看到$excludesvar 包含我想要的內容;但是當我將它傳遞給 rsync 時,bash 正在對它做一些魔術。我不知道如何避免這種情況。我想這與擴展有關,但我找不到與我的或相關文件類似的問題。

編輯:第一次回答後的程式碼:

function run_backup(){
   excludes=()
   if [ $# -ge 3 ]; then
       echo $3
       excludes+=(--exclude $3)
       while shift && [ -n "$3" ]; do
           echo $3
           excludes+=(--exclude $3)
       done
   else
       excludes+=(--exclude /tmp)
   fi
   set -x
   echo "${excludes[@]}"
}
run_backup /tmp/dummy/ /dummy "/tmp/dummy/save-ignored" "/tmp/dummy/save non'standard ignored" /tmp/toto /tmp/tata /tmp/tutu

但它不適用於包含引號的字元串(至少是簡單的引號)

/tmp/dummy/save-ignored
/tmp/dummy/save non'standard ignored
/tmp/toto
/tmp/tata
/tmp/tutu
++ echo --exclude /tmp/dummy/save-ignored --exclude /tmp/dummy/save 'non'\''standard' ignored --exclude /tmp/toto --exclude /tmp/tata --exclude /tmp/tutu
--exclude /tmp/dummy/save-ignored --exclude /tmp/dummy/save non'standard ignored --exclude /tmp/toto --exclude /tmp/tata --exclude /tmp/tutu

使用數組而不是字元串。

例如:

opt=()
opt+=(--exclude "first")
opt+=(--exclude "another one")

set -x
echo "${opt[@]}"

這將正確處理空格(輸出):

+ echo --exclude first --exclude 'another one'
sudo rsync -azvh \
       -e "ssh  -p 22-i /home/backup/.ssh/mykey "\
       --progress \
       --delete \
       ${excludes} \
       ${source} \
       unraid@69.69.69.69:$target
}

引用自:https://unix.stackexchange.com/questions/715646