我有一个很大的目录树,只想复制具有特定名称的文件。我还想保留目录结构、逐步更新和维护元数据,所以这rsync
似乎是自然而然的选择。但是,我无法使语法正常工作。请考虑以下示例结构:
$ find .
.
./filter.txt
./dest
./source
./source/no
./source/fold1
./source/fold1/yes
./source/fold1/no
./source/fold2
./source/fold2/no
./source/fold2/yes
因此,我有一个源文件夹,其中包含名为yes
(复制) 和no
(不复制) 的子文件夹和文件。基于其他一些问题(例如https://serverfault.com/questions/770728/rsync-exclude-all-directories-except-a-few) 我一直在尝试使用一个包含我想要的文件但排除其他所有内容的过滤文件。我尝试了几种方法,但不起作用的简单过滤文件是:
$ cat filter.txt
+ /fold1/yes
- *
$ rsync -avv --progress --include-from=filter.txt source/ dest/
sending incremental file list
[sender] hiding file no because of pattern *
[sender] hiding directory fold1 because of pattern *
[sender] hiding directory fold2 because of pattern *
delta-transmission disabled for local transfer or --whole-file
total: matches=0 hash_hits=0 false_alarms=0 data=0
sent 59 bytes received 86 bytes 290.00 bytes/sec
total size is 0 speedup is 0.00
更改顺序或使用略有不同的语法(例如*/yes
,yes
)不会改变任何内容。在最终实现中,我希望能够包含所有yes
文件而不描述它们的文件夹,此外还有许多其他文件,no
因此单独排除它们不是一个好的解决方案。似乎- *
过滤器行排除了所有内容,无论其上方或下方包含什么,但这与我看到的其他信息不一致。
我怎样才能仅 rsync 特定命名的文件(在子文件夹中)而排除所有其他文件?
我见过一些类似的问题,但(如上所述)它们似乎不能解决我的问题,例如:https://serverfault.com/questions/770728/rsync-exclude-all-directories-except-a-few https://serverfault.com/questions/1063730/rsync-exclude-all-files-in-dir-except-specific-files。
编辑1 根据@harrymc,明确包含文件夹和文件的过滤器适用于该文件:
$ cat filter2.txt
+ /fold1/
+ /fold1/yes
- *
$ rsync -avv --progress --include-from=filter2.txt source/ dest/
sending incremental file list
[sender] hiding file no because of pattern *
[sender] showing directory fold1 because of pattern /fold1/
[sender] hiding directory fold2 because of pattern *
[sender] showing file fold1/yes because of pattern /fold1/yes
[sender] hiding file fold1/no because of pattern *
delta-transmission disabled for local transfer or --whole-file
[generator] risking file fold1/yes because of pattern /fold1/yes
./
fold1/
fold1/yes
0 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=0/3)
total: matches=0 hash_hits=0 false_alarms=0 data=0
sent 157 bytes received 178 bytes 670.00 bytes/sec
total size is 0 speedup is 0.00
编辑2 根据接受的答案,满足我的需求的通用过滤器是:
+ */
+ */yes
- *
这将自动包含每个yes
文件,同时排除所有其他文件。
答案1
问题的解释来自于令人困惑的消息“由于模式 * 而隐藏文件号”。
在帖子中找到了一个很好的解释 rsync --include-from 语法:
如果模式排除了特定的父目录,则它会导致更深的包含模式无效,因为 rsync 没有通过层次结构的排除部分下降。当使用尾随“*”规则时,这一点尤为重要。例如,这将不起作用:
+ /some/path/this-file-will-not-be-found + /file-is-included - *
这会失败,因为父目录“some”被“*”规则排除,因此 rsync 永远不会访问“some”或“some/path”目录中的任何文件。一种解决方案是要求使用单个规则“+ */”(将其放在“- *”规则之前的某个位置)包含层次结构中的所有目录,并可能使用 --prune-empty-dirs 选项。另一种解决方案是为所有需要访问的父目录添加特定的包含规则。例如,这组规则可以正常工作:
+ /some/ + /some/path/ + /some/path/this-file-is-found + /file-also-included - *
您可能必须重新定义您的包含文件列表。
问题是父文件夹/fold1
被排除并且也需要被包括在内。
根据这个解释,该文件filter.txt
需要写成:
+ /fold1/
+ /fold1/yes