2012-12-27 15 views
1

我想在一個bash腳本里面的單個調用中rsync多個目錄,並且遇到引用路徑的語法問題。rsync帶引號的路徑的多個目錄

這裏就是我想:

backuppath='/path/to/backup/folders/' 
declare -a backupitems=('folder1' 'folder2') 
backupitems=(${backupitems[@]/#/\"$backuppath}) 
backupitems=(${backupitems[@]/%/\"}) 
backup=${backupitems[@]} 

rsync ${backup} /path/to/destination 

我得到一個link_stat錯誤說了"/path/to/current/directory"/path/to/backup/folders/folder1""沒有這樣的文件或目錄,然後同樣的錯誤的文件夾2。所以它看起來就像我想要的那樣生成引用的路徑,但rsync會將路徑解釋爲相對路徑,並將路徑添加到前面當前目錄的路徑中。 rsync的正常工作,如果我做

backuppath='path/to/backup/folders/folder1' 
rsync "${backuppath}" /path/to/destination 

把報價爲rsync命令,但我不能夠與多個文件夾的一個變量中,因爲它把多個目錄,長單路做到這一點。我讓腳本使用第二種方法工作,方法是遍歷文件夾並在每個文件夾上調用rsync,但由於腳本的其他部分處理文件夾的方式,此方法稍微笨拙一些,所以我想要獲得第一種方法如果有一個快速解決方案,工作。

編輯:

對於上面的頂配版本,不帶空格的任何目錄名的,我看到使用下面的命令set -vx: 的rsync「「/路徑/到/ backup /文件夾/文件夾1 「」 ' 「/路徑/到/ backup /文件夾/文件夾2」'/路徑/目的地

,我得到了以下錯誤消息/:由@kdubs

rsync: link_stat "/path/to/current/directory/"/path/to/backup/folders/folder1"" failed: No such file or directory (2) 

如果我使用的版本建議,那麼當路徑中沒有空格時,所有東西都可以工作。

當有路徑空間,kdubs在命令版本的結果:

的rsync /路徑/到/備份/文件夾/文件夾1 /路徑/到/備份/文件夾/文件夾2 /路徑/到/目的地

和錯誤:

rsync: link_stat "/path/to/back" failed: No such file or directory (2) 
rsync: link_stat "/path/to/back up/up/folder1" failed: No such file or directory (2) 

我的第一個版本需要額外的調整用的空間工作,因爲擴大與[@]的陣列並創建由封閉與(擴展一個新的數組)導致將路徑中的空間分解爲多個數組元素(見Tonin的答案在下面)。

+0

很好的問題,升值的示例代碼。但是..將更容易診斷您的問題,插入實際的錯誤消息並將其格式化爲代碼。也可以嘗試用'set -vx; rsync ...;設置+ vx'。祝你好運。 – shellter

回答

4

將變量嵌入變量中並沒有什麼用處。做這類事情的最好方法是在擴展變量時在變量周圍放置雙引號,並將數組展開爲"${arrayname[@]}" - 這樣bash會將數組中的每個元素作爲單獨的單詞處理,即使它們包含空格或其他shell元字符。棘手的是前面添加$ backuppath陣列中的每個元素,但你必須是正確的方法(不是把引號圍繞它,而不是在值等):

backuppath='/path/with spaces/' 
backupitems=('folder 1' 'folder 2') # declare -a is optional 
backupitempaths=("${backupitems[@]/#/$backuppath}") 

rsync "${backupitempaths[@]}" /path/to/destination 
+0

絕對是最好的答案!該消息是:_使用更多引號_! '+ 1' –

+0

謝謝!這個答案更接近我最初尋找的東西 - 組合數組,空格和引號時使用的正確語法。 –

0

擺脫那些報價:

backuppath='/path/to/backup/folders/' 
declare -a backupitems=('folder1' 'folder2') 
backupitems=(${backupitems[@]/#/$backuppath}) 
backup=${backupitems[@]} 

rsync ${backup} /path/to/destination 
+0

嗯,對不起,我讓示例代碼太泛泛。這適用於示例中的路徑,但不適用於包含空格的路徑,如'/ path/to/back up/folders /' - 這是使用引號的動機。 –

+0

啊。那麼讓我考慮一下。 – kdubs

+0

不要擺脫引號。其實,多用引號_! –

1

在腳本的問題在於這樣的bash定義了一個數組的元素。元素由空格分隔。因此,當您將修改過的數組元素重新分配給數組時,實際上創建的元素比您首先創建的要多。你可以在數組聲明和每個賦值之後添加一個echo ${#backupitems[@]}

最後,當你在$backup變量中壓扁數組時,bash通過讓rsync相信它給出了相對路徑,甚至使情況更加惡化。

爲了解決這個問題,我會(在路徑或任何)使用下面的腳本與空間中的文件名工作:

backuppath='/path/to/backup/folders/' 
declare -a backupitems=('folder 1' 'folder 2') 
PIFS=$IFS 
# prevents creating new elements from the original array 
IFS='' 
backupitems=(${backupitems[@]/#/$backuppath}) 

rsync ${backupitems[@]} /path/to/destination 
IFS=$PIFS 

腳本redeclares的IFS變量,它改變了關於記錄分隔符bash的行爲當創建一個數組。儘管如此,您的腳本與$backup變量不能再使用,否則在實際投入使用之前會變平。我們希望這不是一個要求。

+0

是的,那有用,謝謝!備份變量不重要。關於你的代碼的一個注意事項是:當我測試它時,似乎可以在'rsync'命令之前加上'IFS = PIFS'(在rsync'調用中似乎不需要IFS更改)。 backupitems在腳本中的rsync調用之前定義了幾行。看起來好像我不需要通過該代碼掛在修改後的IFS上。 –

+0

您是否需要使用$ IFS保存IFS?並用$ PIFS恢復它 – kdubs

+0

@ ws_e_c421我不確定在調用rsync之前可以恢復IFS。在我的機器上(OSX 10.8上的bash 3.2.48)如果我之前恢復它,rsync調用失敗。但你的里程可能會有所不同... – Tonin