bash 脚本中 rsync 的引用排除问题

Issues quoting exclusions for rsync in bash script

我正在使用 bash 脚本通过 rsync 同步 Web 文件夹。我正在使用一组要排除的文件夹和文件,但在为排除列表转义这些项目时遇到问题...

我的排除列表是这样定义的...

SYNC_EXCLUSIONS=(
    '/exclude_folder_1'
    '/exclude_folder_2'
    '.git*'
    '.svn'
)

然后我像这样构建我的排除字符串...

exclusions='';
for e in "${SYNC_EXCLUSIONS[@]}"
do
    exclusions+=" --exclude='$e'";
done

最后我执行了我的 rsync...

rsync --recursive --delete $exclusions "$DEPLOYMENT_WORK_DIR/" "$DEPLOYMENT_ROOT/"

如果我回显命令,它看起来很完美,如果我复制并在提示符下执行它,它就可以正常工作。但是,当脚本中 运行 时,排除项将被忽略。

我发现如果我从每个排除的项目周围删除单引号,它将起作用,就像这样...

exclusions+=" --exclude=$e";

虽然我不想这样做,以防万一我需要排除带有空格或特殊字符的文件夹。

有什么方法可以在保留排除项周围的引号的同时使它在脚本中起作用?我已经尝试了引号和反斜杠等的各种组合,但我尝试过的任何一个都不起作用。

您根本无法为此构建字符串——请参阅 BashFAQ #50 以了解有关原因的广泛讨论。建立一个数组。

exclusions=( )
for e in "${SYNC_EXCLUSIONS[@]}"; do
    exclusions+=( --exclude="$e" )
done

rsync --recursive --delete "${exclusions[@]}" "$DEPLOYMENT_WORK_DIR/" "$DEPLOYMENT_ROOT/"

...好吧,根本无法构建字符串,除非您要使用 eval 来执行它。以不易出现 shell 注入漏洞的方式执行此操作需要注意,但是:

printf -v exclusions_str '--exclude=%q ' "${SYNC_EXCLUSIONS[@]}"
printf -v rsync_cmd 'rsync --recursive --delete %s %q %q' \
  "$exclusions_str" "$DEPLOYMENT_WORK_DIR/" "$DEPLOYMENT_ROOT/"
eval "$rsync_cmd"