rsync 某些文件,不包括其余文件,忽略 .svn/ 目录,递归

can*_*cas 22 networking bash file-sharing rsync regular-expression

我正在使用rsync将一些文件从共享复制到另一个。

递归地,我需要:

  • 删除从源中删除的目标文件
  • 仅同步.php.js文件
  • 排除所有其他文件类型
  • 不要删除.svn/目的地的目录

如果我使用这个:

rsync -zavC --delete --include='*.php' --include='*.js' --exclude="*" \
    /origin /destination
Run Code Online (Sandbox Code Playgroud)

Thenrsync不是递归的,因为exclude="*"排除所有文件和文件夹。

如果我添加,--include="*/"则该.svn/目录将被删除(它也被包含在内)。

我该如何解决这个令人兴奋的困境?

uname -a

Linux tux 3.9.2-1-ARCH #1 SMP PREEMPT 星期六 5 月 11 日 20:31:08 CEST 2013 x86_64 GNU/Linux

rsync 版本:

rsync 3.0.9-6
Run Code Online (Sandbox Code Playgroud)

slm*_*slm 14

第一次尝试(无效)

除了文件之外,您还需要包括目录:

rsync -zavC --delete --include '*/' --include='*.php' --include='*.js' \
     --exclude="*" /media/datacod/Test/ /home/lucas/Desktop/rsync/
Run Code Online (Sandbox Code Playgroud)

第二次尝试

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/
Run Code Online (Sandbox Code Playgroud)

测试数据

我编写了这个脚本来创建一些示例数据来测试它。这是那个脚本,setup_svn_sample.bash

#!/bin/bash

# setup .svn dirs
mkdir -p dir{1,2}/dir{1,2,3,4}/.svn

# fake data under .svn
mkdir -p dir1/dir{1,2,3,4}/.svn/origdir
mkdir -p dir2/dir{1,2,3,4}/.svn/keepdir

# files to not sync
touch dir1/dir{1,2,3,4}/file{1,2}

# files to sync
touch dir1/dir{1,2,3,4}/file1.js
touch dir1/dir{1,2,3,4}/file1.php
Run Code Online (Sandbox Code Playgroud)

运行它会产生以下目录:

源目录

$ tree -a dir1
dir1
|-- dir1
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
|-- dir2
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
|-- dir3
|   |-- file1
|   |-- file1.js
|   |-- file1.php
|   |-- file2
|   `-- .svn
|       `-- origdir
`-- dir4
    |-- file1
    |-- file1.js
    |-- file1.php
    |-- file2
    `-- .svn
        `-- origdir
Run Code Online (Sandbox Code Playgroud)

目标目录

$ tree -a dir2
dir2
|-- dir1
|   `-- .svn
|       `-- keepdir
|-- dir2
|   `-- .svn
|       `-- keepdir
|-- dir3
|   `-- .svn
|       `-- keepdir
`-- dir4
    `-- .svn
        `-- keepdir
Run Code Online (Sandbox Code Playgroud)

运行上面的rsync命令:

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/
sending incremental file list
dir1/file1.js
dir1/file1.php
dir2/file1.js
dir2/file1.php
dir3/file1.js
dir3/file1.php
dir4/file1.js
dir4/file1.php

sent 480 bytes  received 168 bytes  1296.00 bytes/sec
total size is 0  speedup is 0.00
Run Code Online (Sandbox Code Playgroud)

结果 dir2 之后:

$ tree -a dir2
dir2
|-- dir1
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
|-- dir2
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
|-- dir3
|   |-- file1.js
|   |-- file1.php
|   `-- .svn
|       `-- keepdir
`-- dir4
    |-- file1.js
    |-- file1.php
    `-- .svn
        `-- keepdir
Run Code Online (Sandbox Code Playgroud)

为什么有效?

此脚本的关键部分是利用rsync. 过滤器允许您在命令的各个点从匹配集中删除文件。所以在我们的例子中,我们正在过滤任何与模式匹配的文件*/.svn*。修饰符-rs_告诉过滤器我们要在源端和目标端过滤。

摘自 rsync 手册页的 FILTER NOTES 部分

  • 一个小号用来表示该规则适用于发送方。当规则影响发送方时,它会阻止文件传输。除非--delete-excluded指定,否则默认规则会影响双方 ,在这种情况下,默认规则仅成为发送方。另请参阅隐藏 (H) 和显示 (S) 规则,这是指定发送方包含/排除的另一种方法。

  • 一个[R 是用于指示该规则适用于接收侧。当规则影响接收方时,它会阻止文件被删除。有关更多信息,请参阅 s 修饰符。另请参阅保护 (P) 和风险 (R) 规则,它们是指定接收方包含/排除的另一种方法。

有关更多详细信息,请参阅man rsync

解决这个问题的技巧(提示使用--dry-run

在描述如何做到这一点时,我想我会提到--dry-run切换到rsync. 这对于在没有rsync实际发生的情况下看到会发生什么非常有用。

例如

使用以下命令将进行测试运行并向我们展示背后的决策逻辑rsync

rsync --dry-run -avvzC --filter='-rs_*/.svn*' --include="*/" \
     --include='*.js' --include='*.php' --exclude="*" --delete dir1/ dir2/
sending incremental file list
[sender] showing directory dir3 because of pattern */
[sender] showing directory dir2 because of pattern */
[sender] showing directory dir4 because of pattern */
[sender] showing directory dir1 because of pattern */
[sender] hiding file dir1/file1 because of pattern *
[sender] showing file dir1/file1.js because of pattern *.js
[sender] hiding file dir1/file2 because of pattern *
[sender] showing file dir1/file1.php because of pattern *.php
[sender] hiding directory dir1/.svn because of pattern */.svn*
[sender] hiding file dir2/file1 because of pattern *
[sender] showing file dir2/file1.js because of pattern *.js
[sender] hiding file dir2/file2 because of pattern *
[sender] showing file dir2/file1.php because of pattern *.php
[sender] hiding directory dir2/.svn because of pattern */.svn*
[sender] hiding file dir3/file1 because of pattern *
[sender] showing file dir3/file1.js because of pattern *.js
[sender] hiding file dir3/file2 because of pattern *
[sender] showing file dir3/file1.php because of pattern *.php
[sender] hiding directory dir3/.svn because of pattern */.svn*
[sender] hiding file dir4/file1 because of pattern *
[sender] showing file dir4/file1.js because of pattern *.js
[sender] hiding file dir4/file2 because of pattern *
[sender] showing file dir4/file1.php because of pattern *.php
[sender] hiding directory dir4/.svn because of pattern */.svn*
delta-transmission disabled for local transfer or --whole-file
[generator] risking directory dir3 because of pattern */
[generator] risking directory dir2 because of pattern */
[generator] risking directory dir4 because of pattern */
[generator] risking directory dir1 because of pattern */
[generator] protecting directory dir1/.svn because of pattern */.svn*
dir1/file1.js
dir1/file1.php
[generator] protecting directory dir2/.svn because of pattern */.svn*
dir2/file1.js
dir2/file1.php
[generator] protecting directory dir3/.svn because of pattern */.svn*
dir3/file1.js
dir3/file1.php
[generator] protecting directory dir4/.svn because of pattern */.svn*
dir4/file1.js
dir4/file1.php
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 231 bytes  received 55 bytes  572.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)
Run Code Online (Sandbox Code Playgroud)

在上面的输出中,您可以看到./svn目录受到我们的过滤规则的保护。调试rsync.

参考


can*_*cas 10

好的,经过多次尝试,我整理了一下:

rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' \
    --include='*/' --exclude='*' --prune-empty-dirs \
    --filter "protect .svn/" /origin /destination
Run Code Online (Sandbox Code Playgroud)

谢谢