Bash

Bash:讓建構的數組作為參數列表起作用?

  • August 1, 2018

我對 borgbackup 有這個問題,但是因為反應是一樣的,所以我將rsync在我的範例中使用。

我想通過為每個參數添加一個前綴來建構一個參數數組,然後將該數組賦予rsync. 但rsync就像它不存在一樣。

使用此腳本:

#!/usr/bin/env bash
#

declare -a exclude_String
for excludestr in $(cat ./list); do
   exclude_String+=(--exclude=$excludestr)
done
rsync "${exclude_String[@]}" . $Destination

./list

'/home/*'
'*.vim*'

Aps正在執行的程序確實正確顯示了參數:

/usr/bin/rsync --exclude='*.vim*' --exclude='/home/*' . DESTINATION

rsync仍然表現得好像他們不在那裡。我在這個主題上發現了這個問題,所以我嘗試了:

#!/usr/bin/env bash
#

declare -a exclude_String
exclude_String+=(--exclude='/home/*')
exclude_String+=(--exclude='*.vim*')

rsync "${exclude_String[@]}" . $Destination

這實際上奏效了。

我對shell擴展和其他東西還不太了解,我試圖在整個地方引用和雙引號只是為了看看我是否能找到一些東西,但沒有運氣。

關於如何實現這一目標的任何想法?

如果文件實際上包含'/home/*'帶有引號的 ,則引號將出現在excludestr循環中的值中,然後出現在您提供給的參數中rsync。在這種情況下,它們不是 shell 命令的一部分,只是命令替換的擴展值的一部分。

另一方面,如果你寫exclude_String+=(--exclude='/home/*'),現在引號shell 命令的一部分,並在該命令的處理過程中被刪除。(具有製作*普通角色的效果。)

rsync實際上並不期望或處理引號作為排除模式的一部分,它只會將它們視為任何其他字元,並會排除名稱中包含引號的文件。因此,如果您將排除模式作為某個文件中的數據,則不應在此處使用引號。

此外,代替for x in $(cat file),使用while IFS= read -r line; do ...; done < file,或在這種情況下,mapfile -t exclude_String < file。該命令替換cat呼叫分詞,因此您不能有包含空格的排除模式。它還立即在for循環的單詞列表中呼叫模式的萬用字元。這不是你想要的。


一般來說,你需要的是:

excludes=()
while IFS= read -r line; do 
   excludes+=(--exclude="$line")
done < ./list 
rsync "$flags" "${excludes[@]}" . "$destination"

./list包含要排除的模式:

/home/*
*.vim*

(引號"$line"中的引號+=(--exclude="$line")阻止 shell 查找--exclude=something目前目錄中呼叫的文件。)

儘管在 的情況下rsync,您不妨使用--exclude-from

rsync "$flags" --exclude-from=./list . "$destination"

如果您要使用比文件更複雜的東西來提供循環,則可以使用程序替換:

while IFS= read -r line; do
   excludes+=(--exclude="$line")
done < <(some command that produces the exclude patterns)

另請參閱:為什麼我的變數在一個“while read”循環中是本地變數,而不是在另一個看似相似的循環中?

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