rsync --刪除超集目標資料夾

rsync --刪除超集目標資料夾

我有一個rsync進程將來源儲存庫(受版本控制)的內容同步到共用 NFS 掛載中。

這種情況(儘管很糟糕)是目標資料夾包含比來源資料夾更多的內容,因為其他內容從不同的來源同步到目標資料夾。例如,資料夾結構可能如下所示:

來源

a/a1.txt
a/a2.txt
b/b1.txt

目的地

a/a1.txt
a/a2.txt
a/a3.txt
b/b1.txt
c/c1.txt

(在此範例中,a/a3.txtc/c1.txt從其他地方同步到目的地。實際上,這涉及多個其他來源,並且這些來源的內容/流程不會受到影響。)

現在假設來源資料夾刪除了該a/a2.txt檔案。使用現有設置,該檔案不會在目標位置被刪除;但使用--delete會導致其他文件被刪除,並且要求不要這樣做。

如何--delete在這個rsync上使用而又滿足要求?由於來源目錄是受版本控制的,因此很容易獲得該目錄的前後情況,因此可以使用原始來源目錄作為參考來計算差異備份,但這是最好的方法嗎?

答案1

你不能rsync --delete這樣使用。它是無狀態的,並且不記錄運行期間刪除了哪些檔案。該--delete標誌只是指示rsync刪除目標上不存在於來源上的每個檔案。

為了實現這種受限刪除,我認為您需要維護自己的狀態。既不rsyncunison不能為你做這件事。

以下不是完整的錯誤安全解決方案;這是一個起點。 (但是,它確實處理具有奇怪名稱的檔案 - 包括那些包含嵌入換行符的檔案。)

假設有兩個目錄srcdst。 (就本範例而言,本地或遠端並不重要dst。)

# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z > .state.src

每次我們執行備份時,請執行以下程式碼

# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/

# Determine the set of files to delete in "dst/"
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z | tee .state.src.new |
    LC_ALL=C comm -z - -13 .state.src |
    ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'

# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src

如果您的版本comm(例如我的版本)早於 GNU coreutils 8.25 並且沒有該-z標誌,您可以使用以下替代解決方法:

# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | tr '\0\n' '\n\0' | LC_ALL=C sort > .state.src

每次我們執行備份時,請執行以下程式碼

# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/

# Determine the set of files to delete in "dst/"
( cd src && find . -type f  -print0 ) | tr '\0\n' '\n\0' | LC_ALL=C sort | tee .state.src.new |
    LC_ALL=C comm -13 - .state.src |
    tr '\0\n' '\n\0' |
    ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'

# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src

相關內容