我有一个文本文件,其中包含目录列表及其绝对路径
$ cat DirectoriesToCopy.txt
/data/Dir1
/data/Dir2
我想使用 rsync 将所有这些目录复制到另一个位置,保留其绝对路径。
我尝试了以下 rsync 命令,但它不起作用
rsync -avr --include-from=DirectoriesToCopy.txt --exclude='*/' --exclude='/*' / /media/MyDestination/
这里出了什么问题?
答案1
我想使用 rsync [从列表]复制所有这些目录,保留其绝对路径到另一个位置
不要使用--include
或--filter
变体,因为这只会让事情变得混乱。相反,使用--files-from=_filename_
. (如果您这样做,请确保您这样做地段的测试。)
在文件中创建目录列表,每行一个目录/文件。
将 rsync
--files-from=
与上述文件一起使用。使用
--relative
/-R
选项确保将源路径名复制到目标的末尾。即使您有
-a
选择,也请包括-r
.从手册页:在这两种情况下,如果启用了 -r 选项,则该 dir 的整个层次结构也将被传输(请记住 -r 需要使用 --files-from 显式指定,因为 -a 并未暗示 -r)。
完整命令:
rsync ${DEBUG:+-nv} -arR --files-from=<list_of_files.txt> <top-level-dir> <target-dir>
(文件在文件列表.txt必须是相对的或发现于顶级目录)
(如果设置了 DEBUG,rsync 仅打印出可能已复制的内容。)
答案2
使用以下命令:
rsync -av --include-from=DirectoriesToCopy.txt --include /data/ --exclude='/data/*' --exclude='/*/' / /media/MyDestination/
您需要显式包含 /data/ ,您也可以将其添加到文件的列表中。然后排除所有其他目录(对于包含/排除,顺序很重要)。
请注意,您对 的使用-r
是多余的,因为它包含在-a
.
编辑:您还可以通过以下方式实现相同的结果:
rsync -av --relative /data/Dir1 /data/Dir2 /media/MyDestination/
rsync 并不是强迫您做一些困难的事情来复制几个目录,它只是为您提供了多种方法来完成同一件事;在某些情况下,采用包含/排除方式可能更适合,在这里我会执行上面的 --relative 操作(如果--relative
您最终不会得到/media/MyDestination/Dir1
and /media/MyDestination/Dir2
,--relative
整个源路径都会复制到目标)。
答案3
这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 - *
在你的情况下,我认为最简单的方法是预处理要包含的目录列表,以便每当你包含时/path/to/foo
,你还包含所有父目录(,,/path/to
),并且还包含原始目录的子目录(),以及之后所有这些都有一个规则,排除之前未列出的所有内容 ( )。/path
/
/path/to/foo/***
*
<DirectoriesToCopy.txt awk '
{print "+ " $0 "/***"; while (sub(/\/+[^\/]+\/*$/, "/")) print "+ " $0}
END {print "- *"}
' >rsync-rules.txt
rsync -avr --include-from=rsync-rules.txt / /media/MyDestination/