我有一个小的rsync脚本:
OPTS="--some --long --opts"
ORIGIN="/folder/xy/"
DESTINATION="/backups/xy/"
EXCLUDES=( "/dir1" "/dir2" "/dir3" )
PREFIXED_EXCLUDES=( ${EXCLUDES[@]/#/"--exclude=""} ) #prepend <--exclude=">
ESCAPED_EXCLUDES=( ${PREFIXED_EXCLUDES[@]/%/"""} ) #append <">
(1) echo rsync $OPTS ${ESCAPED_EXCLUDES[@]} $ORIGIN $DESTINATION
(2) rsync $OPTS ${ESCAPED_EXCLUDES[@]} $ORIGIN $DESTINATION
(3) eval rsync $OPTS ${ESCAPED_EXCLUDES[@]} $ORIGIN $DESTINATION
(1) 将完全按照我想要的方式回显命令
(2)忽略--排除参数,但只有它们,其他参数有效
(3)工作正常
为什么没有eval
就不起作用?我试图想出一个更简单的例子,但没有想到。
我怀疑这会起作用:
EXCLUDE_DIRS=( "/dir1" "/dir2" "/dir3" )
EXCLUDES=()
for dir in "${EXCLUDE_DIRS[@]}"; do
EXCLUDES+=( "--exclude=$dir" )
done
rsync $OPTS "${EXCLUDES[@]}" "$ORIGIN" "$DESTINATION"
上面所有引用(或缺乏引用)都是非常刻意的。
您需要使用 eval
,因为扩展变量后不会处理引号。变量扩展进行词拆分和文件名通配,不处理其他特殊字符;如果变量在双引号内展开,则即使这些也不会发生。
你实际上应该写:
eval "rsync $OPTS ${ESCAPED_EXCLUDES[@]} $ORIGIN $DESTINATION"
以避免额外的一轮单词拆分和通关。