我用来rsync
将一些文件从共享复制到另一个共享。
递归地,我需要:
- 删除从源位置删除的目标位置的文件
- 仅同步
.php
和.js
文件 - 排除所有其他文件类型
- 不要删除
.svn/
目标目录
如果我使用这个:
rsync -zavC --delete --include='*.php' --include='*.js' --exclude="*" \
/origin /destination
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
答案1
第一次尝试(没有成功)
除了文件之外,您还需要包含目录:
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) 规则,它们是指定接收方包含/排除的另一种方法。
看人同步更多细节。
解决这个问题的技巧(提示使用--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
.
参考
答案2
好的,经过多次尝试,我解决了这个问题:
rsync -vaiz --delete --exclude=.svn/ --include='*.php' --include='*.js' \
--include='*/' --exclude='*' --prune-empty-dirs \
--filter "protect .svn/" /origin /destination
谢谢
答案3
虽然这不使用 rsync,但另一个选择是使用 find 和 cpio。例如,我有一个名为“照片”的目录以及年份和月份。
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”到 Photos 目录上面的目录,然后:
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
您可以将这种方法用于很多事情,几年前,这就是我们在移动到更大磁盘时复制 / 文件系统的方式,因为它会复制设备文件。