1

我正在尝试在 bash 脚本内的一次调用中同步多个目录,并且在引用路径的语法方面遇到了麻烦。

这是我正在尝试的:

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"",然后是 folder2 的相同错误。因此,它似乎正在生成我想要的引用路径,但 rsync 将路径解释为相对路径并添加到前面当前目录的路径。如果我这样做,rsync 可以正常工作

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

将引号放入 rsync 命令中,但我不能对一个变量中的多个文件夹执行此操作,因为它将多个目录视为一条长路径。我通过遍历文件夹并在每个文件夹上调用 rsync 使脚本使用第二种方法工作,但是由于脚本的其他部分处理文件夹的方式,这种方法稍微有点尴尬,所以我想获得第一种方法如果有一个快速修复工作。

编辑:

对于上面的顶级版本,任何目录名称中都没有空格,我看到以下命令使用set -vx: rsync '"/path/to/backup/folders/folder1"' '"/path/to/backup/folders/folder2 "' /路径/到/目的地

我收到以下错误消息:

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

如果我使用@kdubs 建议的版本,那么当路径中没有空格时一切正常。

当路径中有空格时,kdubs 版本会导致命令:

rsync /path/to/back up/folders/folder1 /path/to/back up/folders/folder2 /path/to/destination

和错误:

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 的回答以下)。

4

3 回答 3

4

在变量中嵌入引号没有任何用处。做这种事情的最好方法是在扩展变量时在变量周围加上双引号,并将数组扩展为"${arrayname[@]}"-- 这样 bash 会将数组的每个元素视为一个单独的单词,即使它们包含空格或其他外壳元字符。棘手的事情是在数组的每个元素前面加上 $backuppath,但你有正确的方法(除了在它周围加上引号,而不是在值中):

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

rsync "${backupitempaths[@]}" /path/to/destination
于 2012-12-28T06:51:16.153 回答
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

该脚本重新声明了IFS在创建数组时更改有关记录分隔符的 bash 行为的变量。不过,与您的脚本略有不同,因为该$backup变量不能再使用,否则您将在实际使用之前将数组展平。让我们希望这不是一个要求。

于 2012-12-27T20:52:25.620 回答
0

摆脱那些引号:

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

rsync ${backup} /path/to/destination
于 2012-12-27T19:37:48.810 回答