Bash:讓建構的數組作為參數列表起作用?
我對 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*'
A
ps
正在執行的程序確實正確顯示了參數:/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)