Bash
rsync 某些文件,不包括其余文件,忽略 .svn/ 目錄,遞歸
我
rsync
用來將一些文件從一個共享複製到另一個。遞歸地,我需要:
- 刪除從源中刪除的目標文件
- 僅同步
.php
和.js
文件- 排除所有其他文件類型
- 不要刪除
.svn/
目的地的目錄如果我使用這個:
rsync -zavC --delete --include='*.php' --include='*.js' --exclude="*" \ /origin /destination
Then
rsync
不是遞歸的,因為exclude="*"
排除了所有文件但也排除了文件夾。如果我添加
--include="*/"
,則.svn/
目錄將被刪除(它也被包括在內)。我該如何解決這個令人震驚的困境?
uname -a
:Linux tux 3.9.2-1-ARCH #1 SMP PREEMPT Sat May 11 20:31:08 CEST 2013 x86_64 GNU/Linux
rsync
版本:rsync 3.0.9-6
第一次嘗試(無效)
除了文件之外,您還需要包含目錄:
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 afterards:
$ 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
. 過濾器允許您在命令的各個點從匹配集中刪除文件。所以在我們的例子中,我們過濾了任何與 pattern 匹配的文件*/.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
.參考