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

时间:2016-08-17 03:03:51

标签: bash rsync

我正在使用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";

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

有什么方法可以让我从脚本中解决这个问题,同时保留被排除项目的引号?我已经尝试了各种引号和反斜杠等组合,而且我尝试过的都没有。

1 个答案:

答案 0 :(得分:3)

您根本无法为此构建字符串 - 请参阅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"