以下代码片段是我正在处理的一个更大的 Bash 脚本的一部分。我的目的是将输入变量作为参数传递给 Rsync。
我设法使其大部分工作,除了“--exclude”参数的参数:
INCLUDE="/.vim*,/.git*,/.ssh,.bash_aliases,.bashrc"
rsync ${DRYRUNARG} -avzhP --delete ${SOURCE_DIRS} \
--include=${INCLUDE} \
--exclude={/VirtualBox_VMs/*/Snapshots,/snap,/Downloads,/.*} \
${MNTPNT}${DEST_DIR}
该代码非常适合我的需要,但我仍然希望看到那些必须由变量定义的排除目录。
我需要的结果代码应该是这样的:
INCLUDE="/.vim*,/.git*,/.ssh,.bash_aliases,.bashrc"
EXCLUDE="/VirtualBox_VMs/*/Snapshots,/snap,/Downloads,/.*"
rsync ${DRYRUNARG} -avzhP --delete ${SOURCE_DIRS} \
--include=${INCLUDE} \
--exclude=${EXCLUDE} \
${MNTPNT}${DEST_DIR}
上面的代码不起作用。该命令执行时没有错误,但无法排除任何内容。有趣的是,如果我只用一个目录定义 EXCLUDE 变量,它确实可以工作,即使它遵循用于 INCLUDE 变量的相同结构。
我确信我犯了一些愚蠢的错误。它可能在哪里?
答案1
不要将单独条目的列表降级为单个字符串。这使得解析不同的条目变得困难,并且您必须处理可能包含用作分隔符的字符等的条目的问题。此外,rsync
不知道如何解析包含/排除模式的逗号分隔列表。
相反,使用数组:
#!/bin/bash
INCLUDE=( '/.vim*' '/.git*' /.ssh .bash_aliases .bashrc )
EXCLUDE=( '/VirtualBox_VMs/*/Snapshots' /snap /Downloads '/.*' )
然后在这些列表中的每个项目前面插入--exclude
和,创建新列表:--include
exclude_opts=()
for item in "${EXCLUDE[@]}"; do
exclude_opts+=( --exclude="$item" )
done
include_opts=()
for item in "${INCLUDE[@]}"; do
include_opts+=( --include="$item" )
done
然后只需在调用中使用这些新列表rsync
(假设这SOURCE_DIRS
是一些源目录数组):
rsync ${DRYRUNARG:+"$DRYRUNARG"} -avzhP --delete \
"${include_opts[@]}" \
"${exclude_opts[@]}" \
"${SOURCE_DIRS[@]}" \
"$MNTPNT/$DEST_DIR"
在这里,$DRYRUNARG
如果已设置且不为空,则将使用引号引起来,否则它根本不会成为命令行的一部分。
答案2
一种方法是使用变量作为文件输入,例如--exclude-from
:
EXCLUDE_DIRS="VirtualBox_VMs
Downloads
Snapshots"
rsync -arv --exclude-from=<(printf "%s" "$EXCLUDE_DIRS";) $SOURCE $DESTINATION
答案3
我也一直在尝试同样的事情。并且发现这个问题令人困惑。
我能做的最好的事情就是(使用/bin/bash
)将逗号分隔列表转换为分隔列表--exclude
:
INCLUDE="/.vim*,/.git*,/.ssh,.bash_aliases,.bashrc"
EPATHS=("/VirtualBox_VMs/*/Snapshots" "/snap" "/Downloads" "/.*")
for path in "${EPATHS[@]}"; do
EXCLUDE="$EXCLUDE --exclude=$path"
done
rsync -avzhP --delete ${SOURCE_DIRS} \
--include=${INCLUDE} \
$EXCLUDE \
${MNTPNT} ${DEST_DIR}
这是一个不完整且不优雅的解决方案,但它有效。
挥之不去的问题是我无法让它与路径名中的空格一起使用。当我尝试在串联中添加引号时,例如
EXCLUDE="$EXCLUDE --exclude=\"$path\""
bash
似乎用更多的单引号把它粘住了。
如前所述,set -x
这是我的朋友。