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";

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

是否有一些方法可以让这个工作从脚本,同时保留引号周围排除的项目?我已经尝试了各种引号和反斜杠等组合,但没有任何我尝试过的作品。

根本不能为此构建字符串——请参阅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"

最新更新