Rsync 和引号
Rsync and quotes
我写了一个 bash 脚本,其中包含以下内容:
SRC="dist_serv:$HOME/www/"
DEST="$HOME/www/"
OPTIONS="--exclude 'file.php'"
rsync -Cavz --delete $OPTIONS $SRC $DEST
rsync 失败,我不知道为什么,尽管它似乎与 $OPTIONS 变量有关(当我删除它时它起作用)。我尝试使用反斜杠(以及许多其他内容)转义 space,但这没有用。
错误信息是:
rsync: mkdir "/home/xxx/~/public_html/" failed: No such file or directory (2)
我尝试引用变量,这引发了另一个错误("unknown option" 在我的变量 $OPTIONS 上):
rsync: --exclude 'xxx': unknown option
rsync error: syntax or usage error (code 1) at main.c(1422) [client=3.0.6]
在给变量赋值时,你不应该把 $
放在变量名的前面。 SRC
是一个变量,$SRC
是它扩展到的值。
此外,当您将 ~
放在引号中时,它不会扩展为您的主目录的路径。通常最好在脚本中使用 $HOME
,因为此变量 的行为类似于变量 ,而 ~
则不同。
总是引用变量扩展:
rsync -Cavz --delete "$OPTIONS" "$SRC" "$DEST"
除非有某些理由不这样做(很少有)。否则 shell 将对它们执行分词。
用户@Fred 指出你不能在 $OPTIONS
周围使用双引号(在下面的评论中),但如果你使用 OPTIONS='--exclude="file.php"'
应该没问题(注意 =
).
我发现一种非常宝贵的技术是使用位置参数来简化选项列表的处理。
当您将选项放入变量(例如 OPTIONS
变量)时,您需要找到一种方法在值中包含引号,并在引用变量时省略引号。它有效,但你总是一个错字远离难以调试的失败。
改为尝试以下操作。
set -- -Cavz --delete
set -- "$@" --exclude "file.php"
set -- "$@" "dist_serv:~/www/"
set -- "$@" "~/www/"
rsync "$@"
当然,在这种情况下,一切都可以在同一行,但在许多情况下会有条件表达式,例如,您可以省略给定的选项,或 select 差异文件跟...共事。好消息是,您始终使用与在单个命令行中使用的引号相同的引号,这一切都归功于 "$@"
的魔力,它避免了引用(或引用)任何特定变量。
如果实际的位置参数妨碍您,您可以将它们放在变量中,或者创建一个函数来隔离上下文,避免在它们重要的地方触及它们。
我一直在使用这个技巧,并且由于引用导致我作为参数传递给命令的值内部出现问题,我已经不再拔头发了。
使用数组也可以得到类似的结果。
declare -a ARGUMENTS=()
ARGUMENTS=(-Cavz --delete )
ARGUMENTS+=(--exclude "file.php")
ARGUMENTS+=("dist_serv:~/www/")
ARGUMENTS+=("~/www/")
rsync "${ARGUMENTS[@]}"
我写了一个 bash 脚本,其中包含以下内容:
SRC="dist_serv:$HOME/www/"
DEST="$HOME/www/"
OPTIONS="--exclude 'file.php'"
rsync -Cavz --delete $OPTIONS $SRC $DEST
rsync 失败,我不知道为什么,尽管它似乎与 $OPTIONS 变量有关(当我删除它时它起作用)。我尝试使用反斜杠(以及许多其他内容)转义 space,但这没有用。 错误信息是:
rsync: mkdir "/home/xxx/~/public_html/" failed: No such file or directory (2)
我尝试引用变量,这引发了另一个错误("unknown option" 在我的变量 $OPTIONS 上):
rsync: --exclude 'xxx': unknown option
rsync error: syntax or usage error (code 1) at main.c(1422) [client=3.0.6]
在给变量赋值时,你不应该把 $
放在变量名的前面。 SRC
是一个变量,$SRC
是它扩展到的值。
此外,当您将 ~
放在引号中时,它不会扩展为您的主目录的路径。通常最好在脚本中使用 $HOME
,因为此变量 的行为类似于变量 ,而 ~
则不同。
总是引用变量扩展:
rsync -Cavz --delete "$OPTIONS" "$SRC" "$DEST"
除非有某些理由不这样做(很少有)。否则 shell 将对它们执行分词。
用户@Fred 指出你不能在 $OPTIONS
周围使用双引号(在下面的评论中),但如果你使用 OPTIONS='--exclude="file.php"'
应该没问题(注意 =
).
我发现一种非常宝贵的技术是使用位置参数来简化选项列表的处理。
当您将选项放入变量(例如 OPTIONS
变量)时,您需要找到一种方法在值中包含引号,并在引用变量时省略引号。它有效,但你总是一个错字远离难以调试的失败。
改为尝试以下操作。
set -- -Cavz --delete
set -- "$@" --exclude "file.php"
set -- "$@" "dist_serv:~/www/"
set -- "$@" "~/www/"
rsync "$@"
当然,在这种情况下,一切都可以在同一行,但在许多情况下会有条件表达式,例如,您可以省略给定的选项,或 select 差异文件跟...共事。好消息是,您始终使用与在单个命令行中使用的引号相同的引号,这一切都归功于 "$@"
的魔力,它避免了引用(或引用)任何特定变量。
如果实际的位置参数妨碍您,您可以将它们放在变量中,或者创建一个函数来隔离上下文,避免在它们重要的地方触及它们。
我一直在使用这个技巧,并且由于引用导致我作为参数传递给命令的值内部出现问题,我已经不再拔头发了。
使用数组也可以得到类似的结果。
declare -a ARGUMENTS=()
ARGUMENTS=(-Cavz --delete )
ARGUMENTS+=(--exclude "file.php")
ARGUMENTS+=("dist_serv:~/www/")
ARGUMENTS+=("~/www/")
rsync "${ARGUMENTS[@]}"