我有以下结构:
/Users
/build
/.jenkins
/jobs
/Job1
config.xml
someotherfiles.blah
/Job2
config.xml
someotherfiles.blah
/JobN
config.xml
someotherfiles.blah
我想只将config.xml文件备份到另一个文件夹,保持新文件夹中的文件夹结构相同,但要删除/User/build/.jenkins/jobs
我的新文件夹如下所示:
backup/
/Job1
config.xml
/Job2
config.xml
/JobN
config.xml
这可以使用rsync吗?
编辑:意外地在输出中包含了 someotherfiles.blah ,实际上我不想要那些。我想要的只是config.xml文件以及文件夹结构1级。
答案 0 :(得分:3)
这应该有效:
rsync -r --include=Job* --include=config.xml --exclude=* /full/path/to/Users/build/.jenkins/ backup
除非将-R
选项传递给rsync,否则不会将完整路径复制到备份目录。如果您添加Job*
和config.xml
,然后排除*
(订单很重要,因为首次匹配包含或排除规则会确定要复制的内容),您最终得到的结构是想。如果明确的Job*
模式限制太多,手册说您应该能够使用*/
模式:
一种解决方案是要求层次结构中的所有目录 使用单一规则包含:“+ * /”(将其放在“ - *”规则之前的某处)
有关详细信息,请参阅手册页的整个“INCLUDE / EXCLUDE PATTERN RULES”部分。
答案 1 :(得分:2)
您可以使用--relative
选项指定文件夹级别。
从手册:
还可以限制作为指定的每个路径的隐含目录发送的路径信息量。使用发送端的现代rsync(从2.6.7开始),您可以在源路径中插入一个点和一个斜杠,如下所示:
rsync -avR /foo/./bar/baz.c remote:/tmp/
在此示例中,--relative
选项将开始从第二级创建文件夹。在遥控器上:
/tmp
|_ bar
|_ baz.c
答案 2 :(得分:1)
你走了:
find ./build/.jenkins/jobs/* |
grep -i 'someotherfiles.blah' |
cut -d / -f 5- |
rsync -v -r --exclude-from=- ./build/.jenkins/jobs/ ./output
在步骤中,这就是正在发生的事情:
find ./build/.jenkins/jobs/*
这提供了指定路径中的目录/文件列表。它的输出是
./build/.jenkins/jobs/Job1
./build/.jenkins/jobs/Job1/config.xml
./build/.jenkins/jobs/Job1/someotherfiles.blah
./build/.jenkins/jobs/Job2
./build/.jenkins/jobs/Job2/config.xml
./build/.jenkins/jobs/Job2/someotherfiles.blah
./build/.jenkins/jobs/Job3
./build/.jenkins/jobs/Job3/config.xml
./build/.jenkins/jobs/Job3/someotherfiles.blah
然后我们将它传递给grep命令,在那里我们可以放入我们想要过滤的任何模式。在我的例子中,我想要排除someotherfiles.blah
find ./build/.jenkins/jobs/* |
grep -i 'someotherfiles.blah'
输出
./build/.jenkins/jobs/Job1/someotherfiles.blah
./build/.jenkins/jobs/Job2/someotherfiles.blah
./build/.jenkins/jobs/Job3/someotherfiles.blah
现在rsync将从stdin获取要从其同步中排除的模式列表。它需要有相对于其src参数的路径,所以我们从列表中删除了前几个目录。
find ./build/.jenkins/jobs/* |
grep -i 'someotherfiles.blah' |
cut -d / -f 5-
输出:
Job1/someotherfiles.blah
Job2/someotherfiles.blah
Job3/someotherfiles.blah
现在我们使用--exclude-from = - 参数将其传递给它rsync。这将告诉它从stdin中排除文件。
find ./build/.jenkins/jobs/* |
grep -i 'someotherfiles.blah' |
cut -d / -f 5- |
rsync -v -r --exclude-from=- ./build/.jenkins/jobs/ ./output
输出
building file list ... done
Job1/
Job1/config.xml
Job2/
Job2/config.xml
Job3/
Job3/config.xml
sent 318 bytes received 104 bytes 844.00 bytes/sec
total size is 15 speedup is 0.04
此解决方案使用grep从rsync中查找要EXCLUDE的文件列表。您可能希望grep表达式仅对某些文件进行INCLUDE。您也可以使用--include-from = - 参数执行此操作。还有一个变化。以下是完整代码,仅复制config.xml文件
find ./build/.jenkins/jobs/ |
grep -i 'config.xml' |
cut -d / -f 5- |
awk -F/ '{print; while(/\//) {sub("/[^/]*", ""); print}}'|
rsync -v -r --include-from=- --exclude='*' ./build/.jenkins/jobs/ ./output
当您向--exclude列表添加内容时,rsync将不会搜索列表的任何子目录。显然,我们不希望这样,因为我们的Job1,2,3文件夹中有config.xml文件!因此,我们使用awk将我们要搜索config.xml文件的父目录添加到输出中。
之后,我们告诉rsync来自我们的stdin,并且排除其他所有内容('*')
上面的路径使用相对路径,如果使用绝对路径,则根据需要修改路径,并确保cut命令中的-f参数选择要切割的正确的令牌编号。
无论如何,将这些命令保存在.sh文件中,你应该有一个方便的小实用工具。