如何使用Rsync仅复制特定的子目录(多个目录中的相同名称)

And*_*ron 31 rsync centos centos6

我在服务器1上有这样的目录结构:

  • 数据
    • 公司1
      • unique_folder1
      • other_folder
      • ...
    • Company2的
      • unique_folder1
      • ...
    • ...

我希望在服务器2上复制此文件夹结构,但只复制unique_folder1的目录/子目录.即结果必须是:

  • 数据
    • 公司1
      • unique_folder1
    • Company2的
      • unique_folder1
    • ...

我知道这rsync对此很好.我试过'包含/排除'选项但没有成功.

我试过了:

rsync -avzn --list-only --include '*/unique_folder1/**' --exclude '*' -e ssh user@server.com:/path/to/old/data/ /path/to/new/data/
Run Code Online (Sandbox Code Playgroud)

但是,结果,我没有看到任何文件/目录:

receiving file list ... done
sent 43 bytes  received 21 bytes  42.67 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)
Run Code Online (Sandbox Code Playgroud)

怎么了?想法?


附加信息:我有两个服务器的sudo访问权限.我有一个想法 - 使用find命令并cpio一起复制到我需要的内容和使用后的新目录Rsync.但这很慢,有很多文件等.

And*_*ron 28

我找到了原因.至于我 - Rsync以这种方式工作尚不清楚.
所以正确的命令(company1仅限目录)必须是:

rsync -avzn --list-only --include 'company1/' --include 'company1/unique_folder1/***' --exclude '*' -e ssh user@server.com:/path/to/old/data/ /path/to/new/data
Run Code Online (Sandbox Code Playgroud)

即我们需要包括每个父company目录.当然,我们无法company在命令行中手动编写所有这些目录,因此我们将列表保存到文件中并使用它.


我们需要做的最后事情:

1.Generate包括服务器1文件,因此它的内容将是(我使用lsawk):

+ company1/  
+ company1/unique_folder1/***  
...  
+ companyN/  
+ companyN/unique_folder1/***  
Run Code Online (Sandbox Code Playgroud)

2.Copy include.txt到服务器2并使用这样的命令:

rsync -avzn                                        \
      --list-only                                  \
      --include-from '/path/to/new/include.txt'    \
      --exclude '*'                                \
      -e ssh user@server.com:/path/to/old/data/    \
      /path/to/new/data
Run Code Online (Sandbox Code Playgroud)

  • 没关系,我知道了。我正在做`folder **`而不是`folder / ***`。在目录名称后使用斜杠时,需要第三个星号。两个星号和无斜杠方法也可以使用,但是精度较低,因为它还会匹配具有相同基本名称的对等文件夹。 (2认同)
  • 关于三个星号;Rsync手册页定义...`trailing“ dir_name / ***”将匹配目录(就像已经指定了“ dir_name /”)和目录中的所有内容(就像已经指定了“ dir_name / **”一样) )。此行为已在2.6.7版本中添加。 (2认同)

yon*_*ran 17

如果第一个匹配模式排除了目录,则永远不会遍历其所有后代.当你想要包含一个深层目录,company*/unique_folder1/**但是排除其他所有内容时*,你需要告诉rsync包含它的所有祖先:

rsync -r -v --dry-run                       \
    --include='/'                           \
    --include='/company*/'                  \
    --include='/company*/unique_folder1/'   \
    --include='/company*/unique_folder1/**' \
    --exclude='*'
Run Code Online (Sandbox Code Playgroud)

你可以使用bash的大括号扩展来节省一些打字.在大括号扩展之后,以下命令与前一个命令完全相同:

rsync -r -v --dry-run --include=/{,'company*/'{,unique_folder1/{,'**'}}} --exclude='*'
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@yonran,你可以在下面看到 - '包含列表'太大了.这就是为什么列表被放在一个文件中(请参阅下面接受的答案).并感谢"bash的支撑扩展" - 需要尝试一下. (2认同)

小智 5

在许多情况下,Andron's Answer的另一种更易于理解和实现的替代方法是使用该--files-from=FILE选项。对于目前的问题,

rsync -arv --files-from='list.txt' old_path/data new_path/data
Run Code Online (Sandbox Code Playgroud)

list.txt简直是哪里

company1/unique_folder1/
company2/unique_folder1/
...
Run Code Online (Sandbox Code Playgroud)

请注意,-r必须明确包含该标志,因为--files-from关闭了该-a标志的这种行为。它还在我看来,道路建设是从其他的rsync命令不同,在company1/unique_folder1/比赛,但/data/company1/unique_folder1/确实没有