rsync递归地忽略某些文件,其余文件除外,忽略.svn /目录


19

rsync用来将某些文件从共享复制到另一个。

递归地,我需要:

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

如果我使用这个:

rsync -zavC --delete --include='*.php' --include='*.js' --exclude="*" \
    /origin /destination

然后rsync不是递归的,因为exclude="*"排除所有文件,但也排除文件夹。

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

我该如何解决这种令人难以置信的难题?

uname -a

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

rsync 版:

rsync 3.0.9-6

Answers:


13

第一次尝试(无效)

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

rsync -zavC --delete --include '*/' --include='*.php' --include='*.js' \
     --exclude="*" /media/datacod/Test/ /home/lucas/Desktop/rsync/

第二次尝试

rsync -avzC --filter='-rs_*/.svn*' --include="*/" --include='*.js' \
     --include='*.php' --exclude="*" --delete dir1/ dir2/

测试数据

我编写了此脚本来创建一些示例数据以对其进行测试。这是脚本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

运行它会生成以下目录:

源目录

$ 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

目标目录

$ tree -a dir2
dir2
|-- dir1
|   `-- .svn
|       `-- keepdir
|-- dir2
|   `-- .svn
|       `-- keepdir
|-- dir3
|   `-- .svn
|       `-- keepdir
`-- dir4
    `-- .svn
        `-- keepdir

运行上面的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

产生的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

为什么行得通?

该脚本的关键是利用的过滤器功能rsync。过滤器使您可以在命令的各个位置从匹配集中删除文件。因此,在本例中,我们正在过滤与模式匹配的所有文件*/.svn*。修饰符-rs_告诉过滤器我们要在源端和目标端都进行过滤。

摘自rsync手册页的FILTER NOTES部分

  • 使用s表示该规则适用于发送方。当规则影响发送方时,它将阻止文件传输。除非--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)

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

参考文献


正如我上面所说的,已经尝试过了。如果执行此操作,则还将包含.SVN目录(很可能已删除,因为它不存在或未修改)。保持.SVN目录不变是至关重要的。感谢您的尝试!:)
canolucas

-C应该忽略“ .SVN /”,但include="*/"包括它
canolucas

你是对的。应该是.svn,编辑答案。无论如何,重命名后问题仍然存在。-C而且include="*/"似乎不是很亲密的朋友:(
canolucas

10

好吧,经过几次尝试,我对此进行了整理:

rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' \
    --include='*/' --exclude='*' --prune-empty-dirs \
    --filter "protect .svn/" /origin /destination

谢谢


好答案。我的过滤器可以防止.svn/Dirs --prune-empty-dirs变空。另一种方法是复制空目录:rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' --include='*/' --exclude='*' /origin /destination
canolucas

我的方法的关键是--exclude=.svn/之前--include
canolucas

很好的答案。我建议使用exclude ='。svn /',但我认为您想使用-C。恭喜你弄明白了!
slm

0

尽管这不使用rsync,另一个选择是使用find和cpio。例如,我有一个名为“ Photos”的目录,即年份和月份。

Photos
├── 2002
   ├── 2002-03
      ├── 2002-03-30
      ├── 2002-03-31
      └── 2002-03-31-02
   ├── 2002-04
      ├── 2002-04-01
      ├── 2002-04-01-03
      ├── 2002-04-07
      ├── 2002-04-21
      ├── 2002-04-22
      ├── 2002-04-22-02
      └── 2002-04-27
   ├── 2002-05
      ├── 2002-05-02
      ├── 2002-05-03

但是在这里我有jpg,dng,xml和其他东西,我只想要jpg的,所以我会这样做

“ cd”到“照片”目录上方的目录,然后:

find Photos -type f -name "*jpg" -print | cpio -pdmvu /fast

然后就走了

/fast/Photos/2002/2002-04/2002-04-22/bath problem.jpg
/fast/Photos/2002/2002-04/2002-04-22-02/full bath.jpg
/fast/Photos/2002/2002-07/2002-07-10/Broken Top.jpg
/fast/Photos/2002/2002-12/2002-12-28/101-0125_IM~~G.jpg
/fast/Photos/2002/2002-12/2002-12-28/small-101-0125_IM~~G.jpg
/fast/Photos/2003/2003-01/2003-01-19/k1.jpg
/fast/Photos/2003/2003-01/2003-01-19/k2.jpg
/fast/Photos/2003/2003-02/2003-02-23/quinn.jpg
/fast/Photos/2003/2003-05/2003-05-04/all.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0015_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0006_2_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0006_r1.jpg
/fast/Photos/2003/2003-05/2003-05-09/100_0007_2_r1.jpg

您可以在很多事情上使用此方法,几年前,这就是我们复制/文件系统到较大磁盘时的方式,因为它会复制设备文件。


那没有回答问题。
RalfFriedl

如果使用以下命令,它将执行以下操作:find / origin -type f(-name“ .php” -o -name“ .js”)-print | cpio -pdmvu / destination仅* .php和* .js文件位于目标目录中。
lxtwin
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.