rsync文本文件中具有绝对路径的目录列表


9

我有一个文本文件,其中包含目录列表及其绝对路径

$ cat DirectoriesToCopy.txt

/data/Dir1
/data/Dir2

我想使用rsync复制所有这些目录,将其绝对路径保留到另一个位置。

我尝试了以下rsync命令,但它不起作用

rsync -avr --include-from=DirectoriesToCopy.txt --exclude='*/' --exclude='/*'  /  /media/MyDestination/

这是怎么了?


你想转移/data/Dir1/data/Dir2包括其内容/media/MyDestination/Dir1/media/MyDestination/Dir2?还是要包含该/data零件?该列表有多大?仅在命令行中列出这些条目是否太大?无论如何,您的--exclude陈述会阻止递归。
wurtel 2014年

我也想传输这些目录中的所有文件。该目录中有许多文件,因此我要避免使用所有文件名创建另一个文本文件。
indiajoe 2014年

我想保持自己的完整道路/media/MyDestination/data/Dir2/。我添加了--exclude来防止/中的其他目录和文件被复制。
indiajoe 2014年

在目录列表不是很大的情况下,我想以下选项会更容易rsync -av $(cat DirectotiesToCopy.txt) /media/MyDestination/
indiajoe 2014年

Answers:


6

使用以下命令:

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/media/MyDestination/Dir2--relative将整个源路径复制到目标位置)。


谢谢你的工作。我不得不为使用rsync简单复制目录列表而定义如此仔细的过滤器顺序感到有些惊讶。例如,如果我的目录列表不在一个公用目录/ data /下,而是分散在许多位置,则要定义的过滤器将变得非常复杂。
indiajoe 2014年

查看我对答案的修改。
wurtel

谢谢。因此,如果目录列表不是很大,可以使用--relative标志,如下所示。rsync -av --relative $(cat DirectotiesToCopy.txt) /media/MyDestination/
indiajoe 2014年

是; 记住--relative只是另一种选择。
wurtel 2014年

7

我想使用rsync [从列表中]复制所有这些目录,并将其绝对路径保留到另一个位置

不要使用--include--filter变化,因为这只会使事情变得混乱。而是使用--files-from=_filename_。(如果这样做,请确保进行了大量测试。)

  1. 在文件中创建目录列表,每行一个目录/文件。

  2. 将rsync --files-from=与上述文件配合使用。

  3. 使用--relative/ -R选项以确保将源路径名复制到目标的末尾。

  4. 即使您有-a选择,也请包括-r。从手册页:

    在这两种情况下,如果启用了-r选项,该目录的整个层次结构也将被传输(请注意-r需要使用--files-from明确指定,因为-a并不隐含它)。

完整的命令:

rsync ${DEBUG:+-nv} -arR --files-from=<list_of_files.txt> <top-level-dir>  <target-dir>

list_of_files.txt中的文件必须是相对的或在top-level-dir中找到

(如果设置了DEBUG,则rsync仅打印出可能已复制的内容。)


1
这就是我所需要的!但是,“-include-from”应为“ --files-from”。我还使用了“ --list-only”来预览RSYNC在实际运行之前将执行的操作。
Adambean

1
谢谢,我已经更新了答案。--include-from也可以使用,但是我所说-r的基本上是无关紧要的。
Otheus

2

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/

感谢您的详细说明和创建规则文件的脚本。我现在了解这个问题。我仍然觉得rsync具有--dirs-from = DirectoriesToCopy.txt之类的选项作为所有复杂过滤器的捷径是不错的选择。
indiajoe 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.