如何在rsync的--exclude-from选项中正确排除指定绝对路径文件夹?
rsync同步问题:精准排除指定目录,保留同名其他目录
目录结构
/games/scripts/myscript.sh /games/doom/doom.sh /games/quake/quake.sh /books/scripts/manuscript.txt /books/text/hamlet.txt /books/text/shakespeare.txt
需求
- 同步时保留
/books/scripts目录及内容 - 完全排除
/games/scripts/目录及内容
当前配置
遍历同步的根目录列表(directories.txt)
/games /books
排除规则文件(exclude.txt)
/games/scripts/
执行的rsync命令
/usr/bin/rsync -zaxvrlog --stats \ --exclude-from="exclude.txt" \ --delete --rsh="/usr/bin/ssh -q" \ "kevin"@"myhost.internal":"${directory}" "${directory_stripped}"
问题现象
运行脚本后,/games/scripts/和/books/scripts/都被排除,未同步到本地。尝试调整命令格式,仍无法实现基于服务器根目录的绝对路径排除规则。
问题原因
脚本是逐个同步/games和/books目录,此时rsync会将每个同步的目录作为"源根目录",排除规则中的绝对路径(以/开头)是相对于这个源根目录,而非远程服务器的系统根目录。
比如同步/games时,/games/scripts/会被解析为源根目录/games下的scripts/,从而排除该目录;同步/books时,同样的规则会被解析为源根目录/books下的scripts/,导致该目录也被排除。
解决方案
方案一:按同步目录动态调整排除规则
在遍历脚本中增加判断,仅同步/games时应用排除规则:
for directory in $(cat directories.txt); do directory_stripped=$(basename "$directory") exclude_args="" # 仅当同步/games时排除scripts目录 if [ "$directory" = "/games" ]; then exclude_args="--exclude='scripts/'" fi /usr/bin/rsync -zaxvrlog --stats \ $exclude_args \ --delete --rsh="/usr/bin/ssh -q" \ "kevin"@"myhost.internal":"${directory}" "${directory_stripped}" done
方案二:使用--relative参数保留完整路径,实现绝对路径排除
放弃逐个遍历,一次性同步两个目录,通过-R(--relative)参数保留远程完整路径结构,此时排除规则中的绝对路径会匹配远程服务器的系统根目录:
/usr/bin/rsync -zaxvrlogR --stats \ --exclude-from="exclude.txt" \ --delete --rsh="/usr/bin/ssh -q" \ "kevin"@"myhost.internal":/{games,books} ./
执行后,本地会生成games/和books/目录,其中games/scripts/被排除,books/scripts/正常同步。
内容的提问来源于stack exchange,提问作者Kevin B
相关产品推荐
相关产品推荐

