rsync备份无法包含隐藏目录内特定文件的问题求助
大家好,我最近在用rsync做备份的时候碰到了个棘手的问题:为了避免备份所有隐藏的主目录,我在排除文件里加了.*,结果现在发现有些需要备份的文件/目录刚好在这些隐藏目录下面,也被一起排除了,而且我直接在包含文件里指定这些路径根本不管用。
我目前用的rsync命令是:
rsync --archive --verbose --human-readable --delete --exclude-from='rsync-exclude-files-and-folders' --include-from='rsync-include-files-and-folders' /home/andrea/ /media/andrea/maxtor-Est1000/
我的排除文件rsync-exclude-files-and-folders内容:
.* node_modules snap software VirtualBox VMs condivisa-windows-vm *node_modules* Scaricati Scrivania /package-lock.json /package.json
包含文件rsync-include-files-and-folders内容:
/home/andrea/.var/app/org.mozilla.firefox/cache/mozilla/firefox/oslnwe1t.default-release /home/andrea/.config/libreoffice/4/user
我已经翻遍了rsync的手册页,但就是没找到怎么把已排除目录里的特定文件/目录重新包含进来的方法,请问有没有可行的解决方案?我用的系统是Kubuntu 23.04。
问题原因&解决方案
其实问题出在rsync的规则匹配逻辑上:你先排除了所有.*开头的隐藏目录,这意味着rsync根本不会去遍历这些目录,后面的include规则自然没机会匹配到里面的子路径。要解决这个问题,得调整规则的顺序和写法,让rsync先“放行”需要的隐藏目录父路径,再排除其他隐藏目录:
- 修正包含文件的路径写法
因为rsync的源是/home/andrea/,所以包含文件里的路径要用相对源目录的路径,而不是绝对路径,同时要先包含目标路径的所有父目录(确保rsync会遍历到那里)。修改后的rsync-include-files-and-folders可以写成:
/.var/ /.var/app/ /.var/app/org.mozilla.firefox/ /.var/app/org.mozilla.firefox/cache/ /.var/app/org.mozilla.firefox/cache/mozilla/ /.var/app/org.mozilla.firefox/cache/mozilla/firefox/ /.var/app/org.mozilla.firefox/cache/mozilla/firefox/oslnwe1t.default-release/ /.config/ /.config/libreoffice/ /.config/libreoffice/4/ /.config/libreoffice/4/user/
嫌麻烦的话也可以用通配符简化(注意可能会意外包含其他子内容,按需选择):
/.var/** /.config/libreoffice/4/user/**
- 调整排除文件的规则顺序
把原来的.*排除规则往后放,先添加反向规则保留需要的隐藏目录,修改后的rsync-exclude-files-and-folders内容:
# 先排除不需要的非隐藏目录和文件 node_modules snap software VirtualBox VMs condivisa-windows-vm *node_modules* Scaricati Scrivania /package-lock.json /package.json # 先保留需要的隐藏目录,再排除其他所有隐藏目录 !/.var/ !/.config/libreoffice/ .*
这里要注意:rsync的规则是从上到下匹配,一旦匹配就停止处理后续规则,所以必须把保留规则(!开头的反向排除)放在总排除规则.*之前,这样rsync才会先保留指定的隐藏目录,再排除其他所有隐藏目录。
- 先测试再执行
建议先加上--dry-run参数测试一下,确认规则是否生效,避免误删文件:
rsync --archive --verbose --human-readable --delete --dry-run --exclude-from='rsync-exclude-files-and-folders' --include-from='rsync-include-files-and-folders' /home/andrea/ /media/andrea/maxtor-Est1000/
补充说明
rsync处理规则时是跟着目录遍历顺序走的:如果父目录被排除了,rsync不会进入该目录,自然也不会检查里面的任何子文件或目录的规则。所以必须先让rsync允许遍历那些包含目标文件的父目录,后续的include规则才能生效。
备注:内容来源于stack exchange,提问作者CaneRandagio

