使用Rsync的包含和排除选项按模式包括目录和文件

101

我在使用rsync时遇到了语法问题,我想知道我的情况是否可以使用rsync来处理。首先,我确认rsync在本地主机和远程主机之间正常工作。对目录进行简单同步是成功的。

这是我的文件系统的样子:

uploads/
  1260000000/
    file_11_00.jpg
    file_11_01.jpg
    file_12_00.jpg
  1270000000/
    file_11_00.jpg
    file_11_01.jpg
    file_12_00.jpg
  1280000000/
    file_11_00.jpg
    file_11_01.jpg
    file_12_00.jpg

我想做的是仅在子目录中以“file_11_”开头的文件上运行rsync,并且我希望能够只运行一个rsync作业来同步所有这些子目录中的文件。

这是我正在尝试的命令:

rsync -nrv --include="**/file_11*.jpg" --exclude="*" /Storage/uploads/ /website/uploads/

这导致我的dry run中标记了0个文件进行传输。 我尝试过各种其他组合的--include--exclude语句,但要么仍然得不到结果,要么得到了所有内容,就好像没有设置任何包括或排除选项一样。

有人知道如何实现吗?

3个回答

153
问题在于--exclude="*"表示要排除(例如)1260000000/目录,因此rsync从未检查该目录的内容,因此也从未注意到该目录包含的文件与您的--include匹配。
我认为最接近您想要的是这个:
rsync -nrv --include="*/" --include="file_11*.jpg" --exclude="*" /Storage/uploads/ /website/uploads/

(其中将包括所有目录和所有匹配file_11*.jpg的文件,但不包括其他文件),或者也许是这样的:

rsync -nrv --include="/[0-9][0-9][0-9]0000000/" --include="file_11*.jpg" --exclude="*" /Storage/uploads/ /website/uploads/

(相同的概念,但更加挑剔于它将包含的目录)。

无论哪种情况,需要注意的是--include=...选项需要在--exclude=...选项之前出现,因为当一个文件匹配两个模式时,我们需要前者优先于后者。


1
谢谢!那正是我所需要的。我的情况实际上与你在第二个例子中描述的差不多,但我简化了问题以使问题更加直接。 - Sheldon Chang
13
请注意,例如--include="*/"对于包含您实际想要包括的文件的父级目录非常重要。 - mabraham
29
请注意参数的顺序:--include 必须在 --exclude 之前。 - hfs
@hfs 是的,我认为这应该在答案中提到。在找到这个页面之前,我试图做类似的事情,并知道我需要使用“-include="*/"”,但它仍然无法工作。看到这个答案,我的第一个想法是“这正是我正在做的!”然后我注意到顺序不同了。 - Laurence Gonsalves
另一个关键概念是,“当使用--recursive(-r)选项(这是由-a隐含的),每个路径的每个子组件都从上到下访问,因此包括/排除模式会递归地应用于每个子组件的完整名称”。 - wisbucky
显示剩余2条评论

81

rsync 包含排除模式示例:

"*"         means everything
"dir1"      transfers empty directory [dir1]
"dir*"      transfers empty directories like: "dir1", "dir2", "dir3", etc...
"file*"     transfers files whose names start with [file]
"dir**"     transfers every path that starts with [dir] like "dir1/file.txt", "dir2/bar/ffaa.html", etc...
"dir***"    same as above
"dir1/*"    does nothing
"dir1/**"   does nothing
"dir1/***"  transfers [dir1] directory and all its contents like "dir1/file.txt", "dir1/fooo.sh", "dir1/fold/baar.py", etc...

最后需要注意的是不要仅仅依靠在路径开头使用的星号来评估路径;例如"**dir" (对于单个文件夹或文件可以使用,但对于路径不行),并且请注意超过两个星号对于文件名无效。


13
你的答案是唯一可用的,因为你解释了一般的行为方式。其他答案根据提问者的具体情况过于具体,每种情况需要另一种解决方案!它对我帮助很大! - Peter VARGA
3
可在“rsync”手册的“INCLUDE/EXCLUDE PATTERN RULES”部分找到详尽但不太直观的解释。 - Gerrit-K

27

以下是我的“授人以渔”回答:

Rsync 的语法确实不直观,但了解它是值得的。

  1. 首先,使用 -vvv 查看 rsync 的调试信息。
$ rsync -nr -vvv --include="**/file_11*.jpg" --exclude="*" /Storage/uploads/ /website/uploads/

[sender] hiding directory 1280000000 because of pattern *
[sender] hiding directory 1260000000 because of pattern *
[sender] hiding directory 1270000000 because of pattern *

关键概念在于rsync会递归地对每个目录应用包括/排除模式。一旦匹配到第一个包括/排除模式,处理就停止。

它评估的第一个目录是/Storage/uploadsStorage/uploads1280000000/,1260000000/,1270000000/目录/文件。它们中没有一个匹配file_11*.jpg以进行包括。所有这些都匹配*以进行排除。因此,它们被排除在外,rsync结束。

  1. 解决方法是首先包括所有目录(*/)。然后第一个目录组件将是1260000000/,1270000000/,1280000000/因为它们匹配了*/。下一个目录组件将是1260000000/。在1260000000/中,file_11_00.jpg匹配--include="file_11*.jpg",因此它被包括。以此类推。
$ rsync -nrv --include='*/' --include="file_11*.jpg" --exclude="*" /Storage/uploads/ /website/uploads/

./
1260000000/
1260000000/file_11_00.jpg
1260000000/file_11_01.jpg
1270000000/
1270000000/file_11_00.jpg
1270000000/file_11_01.jpg
1280000000/
1280000000/file_11_00.jpg
1280000000/file_11_01.jpg

https://download.samba.org/pub/rsync/rsync.1


如果你总是输入 --include='*/',那可能意味着界面还有改进的空间。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接