Bash

rsync 某些文件,不包括其余文件,忽略 .svn/ 目錄,遞歸

  • September 22, 2019

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 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.

參考

引用自:https://unix.stackexchange.com/questions/76237