我正在尝试运行 rsync 以根据文件名模式、大小写递归地沿路径复制一些文件不敏感。这是我运行 rsync 的步骤:
$ rsync -avvz --include ='*/' --include='.*[Nn][Aa][Mm][E].*' --exclude='*' ./a/ ./b/
没有复制任何内容,调试输出显示:
[sender] hiding file 1Name.txt because of pattern *
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] hiding directory test1 because of pattern *
[sender] hiding file NaMe.txt because of pattern *
我尝试过使用: --include='*[Nn][Aa][Mm][E]*'
和其他组合,但仍然不起作用。
关于如何使用正则表达式来包含一些文件有什么想法吗?
答案1
rsync 不支持正则表达式。您可以使用 find 和 grep,尽管这有点晦涩难懂。要查找目标文件:
find a/ |
grep -i 'name'
但是它们都以“a/”为前缀 - 这是有道理的,但我们最终想要得到的是一个 rsync 可以接受的包含模式列表,而由于“a/”前缀不适用于 rsync,我将使用 cut 将其删除:
find . |
grep -i 'name' |
cut -d / -f 2-
还有一个问题——我们仍然会错过子目录中的文件,因为 rsync 不会搜索排除列表中的目录。我将使用 awk 将任何匹配文件的子目录添加到包含模式列表中:
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'
剩下的就是将列表发送到 rsync - 我们可以使用参数 --include-from=- 在标准输入上向 rsync 提供模式列表。因此,总的来说:
find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
请注意,源目录“a”通过两个不同的路径引用 - “a/”和“./a/”。这很微妙但很重要。为了使事情更加一致,我将进行最后一次更改,并始终将源目录称为“./a/”。但是,这意味着 cut 命令必须更改,因为 find 结果前面会有一个额外的“./”:
find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/
答案2
我建议使用 rsync 的过滤选项。例如,只需输入:
rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b
第一个过滤规则告诉 rsync 要包含哪些模式。第二个规则用于告诉 rsync 检查其遍历的所有目录。为了防止包含空目录,它们通过-m
选项明确排除。最后一个过滤规则告诉 rsync 处理到目前为止仍未匹配的所有剩余模式。
答案3
如果您使用 ZSH,则可以使用 (#i) 标志关闭区分大小写。示例:
$ touch NAME
$ ls (#i)*name*
NAME
ZSH 还支持排除,其指定方式与常规路径相同,但其初始值为 ~
$ touch aa ab ac
$ ls *~*c
aa ab
您可以链接排除:
$ ls *~*c~*b
aa
最后,您可以指定要返回的文件类型(目录、文件等)。使用 (/) 表示目录,使用 (.) 表示文件。
$ touch file
$ mkdir dir
$ ls *(.)
file
基于这一切,我会执行如下命令:
rsync -avvz *(/) (#i)*name* ./a/ ./b/
(我不认为有必要用这些选择器进行排除)
答案4
尝试使用 C# 脚本,因为这是我最熟悉的语言。我可以创建要包含的文件列表,但有人 rsync 仍然告诉我走开。它创建了文件夹,但忽略了文件。以下是我得到的结果。
首先是目录的内容:
~/mono$ ls -l
total 24
drwxr-xr-x 5 me me 4096 Jan 15 00:36 a
drwxr-xr-x 2 me me 4096 Jan 15 00:36 b
drwxr-xr-x 3 me me 4096 Jan 14 00:31 bin
-rw-r--r-- 1 me me 3566 Jan 15 00:31 test.cs
-rwxr-xr-x 1 me me 4096 Jan 15 00:31 test.exe
-rwxr--r-- 1 me me 114 Jan 14 22:40 test.sh
然后是 C# 脚本的输出:
~/mono$ mono test.exe
/a/myfile/myfileseries.pdf
/a/myfile2/testfile.pdf
调试输出:
~/mono$ mono test.exe | rsync -avvvz --include='*/' --include-from=- --exclude='*' ./a/ ./b/
[client] add_rule(+ */)
[client] parse_filter_file(-,20,3)
[client] add_rule(+ /a/myfile/myfileseries.pdf)
[client] add_rule(+ /a/myfile2/testfile.pdf)
[client] add_rule(- *)
sending incremental file list
[sender] make_file(.,*,0)
[sender] hiding file 1Name.txt because of pattern *
[sender] showing directory myfile2 because of pattern */
[sender] make_file(myfile2,*,2)
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] showing directory test1 because of pattern */
[sender] make_file(test1,*,2)
[sender] hiding file NaMe.txt because of pattern *
[sender] showing directory myfile because of pattern */
[sender] make_file(myfile,*,2)
send_file_list done
send_files starting
[sender] hiding file myfile/myfileseries.pdf because of pattern *
[sender] hiding file myfile2/testfile.pdf because of pattern *
[sender] hiding file test1/test.txt because of pattern *