Rsync和引号

时间:2017-01-16 19:50:52

标签: bash rsync quotes

我用以下内容编写了一个bash脚本:

SRC="dist_serv:$HOME/www/"
DEST="$HOME/www/"
OPTIONS="--exclude 'file.php'"
rsync -Cavz --delete $OPTIONS $SRC $DEST

rsync失败,我无法弄清楚为什么,虽然它似乎与$ OPTIONS变量有关(当我删除它时它会起作用)。我尝试用反斜杠(以及许多其他东西)逃避空间,但这不起作用。 错误消息是:

rsync: mkdir "/home/xxx/~/public_html/" failed: No such file or directory (2)

我尝试引用变量,这会引发另一个错误(我的变量$ OPTIONS上的“未知选项”):

rsync: --exclude 'xxx': unknown option
rsync error: syntax or usage error (code 1) at main.c(1422) [client=3.0.6]

2 个答案:

答案 0 :(得分:0)

在为值赋值时,不应将$放在变量名前面。 SRC是一个变量,$SRC是它展开的值。

此外,当您将其放在引号中时,~不会扩展到主目录的路径。通常最好在脚本中使用$HOME,因为此变量的行为类似于变量~不会这样做。

始终引用变量扩展:

rsync -Cavz --delete "$OPTIONS" "$SRC" "$DEST"

除非有某些理由不(很少有)。 shell会对它们进行分词。

用户@Fred指出您不能在$OPTIONS周围使用双引号(在下面的评论中),但如果您使用OPTIONS='--exclude="file.php"'则应该没问题(请注意{{1} }})。

答案 1 :(得分:0)

我发现一种非常有价值的技术是使用位置参数来轻松使用选项列表。

当您在变量(例如OPTIONS变量)中放置选项时,您需要找到一种在值内包含引号的方法,并在引用变量时省略引号。它可以工作,但是你总是从一个难以调试的失败中解决一个错误。

相反,请尝试以下方法。

set -- -Cavz --delete
set -- "$@" --exclude "file.php"
set -- "$@" "dist_serv:~/www/"
set -- "$@" "~/www/"
rsync "$@"

当然,在这种情况下,所有内容都可以在同一行,但在许多情况下会有条件表达式,例如,您可以省略给定选项,或选择要使用的差异文件。好的方面是,你总是使用在单个命令行中使用的相同引用,这完全归功于"$@"的魔力,它避免了引用(或引用)任何特定变量。

如果实际位置参数受阻,您可以将它们放在变量中,或者创建一个函数来隔离一个上下文,避免在它们重要的地方触摸它们。

我一直都在使用这个技巧,而且由于引用引起的问题导致我的头发问题,我将其作为参数传递给命令。

使用数组可以实现类似的结果。

declare -a ARGUMENTS=()
ARGUMENTS=(-Cavz --delete )
ARGUMENTS+=(--exclude "file.php")
ARGUMENTS+=("dist_serv:~/www/")
ARGUMENTS+=("~/www/")
rsync "${ARGUMENTS[@]}"