我正在使用 bash 脚本通过 rsync 同步 Web 文件夹。我正在使用一系列要排除的文件夹和文件,并且在将这些项目转义为排除列表时遇到问题...
我的排除列表是这样定义的......
SYNC_EXCLUSIONS=(
'/exclude_folder_1'
'/exclude_folder_2'
'.git*'
'.svn'
)
Run Code Online (Sandbox Code Playgroud)
然后我像这样构建排除字符串......
exclusions='';
for e in "${SYNC_EXCLUSIONS[@]}"
do
exclusions+=" --exclude='$e'";
done
Run Code Online (Sandbox Code Playgroud)
最后我执行我的 rsync...
rsync --recursive --delete $exclusions "$DEPLOYMENT_WORK_DIR/" "$DEPLOYMENT_ROOT/"
Run Code Online (Sandbox Code Playgroud)
如果我回显该命令,它看起来很完美,如果我在提示符下复制并执行它,它就会正常工作。但是,当从脚本运行时,排除项将被忽略。
我发现如果我从每个排除的项目周围删除单引号,它就会起作用,就像这样......
exclusions+=" --exclude=$e";
Run Code Online (Sandbox Code Playgroud)
不过,我不想这样做,以防万一我需要排除带有空格或特殊字符的文件夹。
有什么方法可以让它在脚本中工作,同时保留排除项目的引号?我尝试过各种引号和反斜杠等的组合,但我尝试过的都不起作用。
您根本无法为此构建字符串——请参阅BashFAQ #50以获取对其原因的广泛讨论。构建一个数组。
exclusions=( )
for e in "${SYNC_EXCLUSIONS[@]}"; do
exclusions+=( --exclude="$e" )
done
rsync --recursive --delete "${exclusions[@]}" "$DEPLOYMENT_WORK_DIR/" "$DEPLOYMENT_ROOT/"
Run Code Online (Sandbox Code Playgroud)
...好吧,根本无法构建字符串,除非您要使用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"
Run Code Online (Sandbox Code Playgroud)