Rsync

rsync 具有自己後代的目錄

  • February 28, 2022

**tl; dr:**我想要rsync一個目錄到它自己的後代,然後rsync將所述後代返回到原始目錄——包括兩個方向的刪除和排除。

在你問一個明顯的問題之前,“你為什麼要這樣做?” 或指出另一種方法會有多好,這是業務需求。這不是我的選擇,我知道風險,所以放縱我。我不打算進一步證明這種方法的合理性。🙂

細節:

我想要rsync一個目錄到它自己的後代——即,一個“下面”或“裡面”的目錄,例如parentparent/child然後將後代的更改同步回原始目錄,例如,parent/childto parent,包括刪除和兩個方向的排除。在視覺上,我需要這樣做:

parent -> parent/child
parent <- parent/child

困難在於…

  1. 從祖先到後代時防止無限遞歸
  2. 將後代同步回其祖先時,不會在操作中刪除源文件(表現為“文件已消失”錯誤)
  3. 始終尊重例外情況

解決方案分為三個部分。為了…

  1. 排除相對於祖先的後代目錄路徑,例如,child從同步時parent/child
  2. 使用--delete-after標誌而不是 --delete
  3. 使所有排除路徑都相對於源,例如,exclude.txt/var/www/parent/exclude.txt

這是一個測試腳本(帶有一些特殊格式以獲得更好的輸出):

#!/usr/bin/env bash

clear

printf "\n\e[33mrsync version:\n"
printf "%s--------------\e[39m\n"

rsync --version | head -n 1
# rsync  version 2.6.9  protocol version 29

rm -r parent

mkdir -p parent

touch parent/original.txt \
     parent/delete-from-child.txt \
     parent/exclude-from-child.txt

printf "\n\e[33mOriginal state:\n"
printf "%s---------------\e[39m\n"

tree -a --noreport -- parent

printf "\n\e[33mrsync to child:\n"
printf "%s---------------\e[39m\n"

printf "rsync --archive \\n      --delete-after \\n      --exclude=exclude-from-child.txt \\n      "$PWD"/parent/ \\n      "$PWD"/parent/child\n\n"
rsync --archive \
     --delete-after \
     --exclude=exclude-from-child.txt \
     "$PWD"/parent/ \
     "$PWD"/parent/child

tree -a --noreport -- parent; echo

printf "\e[33mMake changes:\n"
printf "%s---------------\e[39m\n"

rm parent/child/delete-from-child.txt
printf "rm parent/child/delete-from-child.txt\n"
touch parent/child/create-in-child.txt
printf "touch parent/child/create-in-child.txt\n"
touch parent/child/exclude-from-parent.txt
printf "touch parent/child/exclude-from-parent.txt\n\n"

printf "\e[33mrsync back to parent:\n"
printf "%s---------------------\e[39m\n"

printf "rsync --archive \\n      --delete-after \\n      --exclude=child \\n      --exclude=exclude-from-child.txt \\n      --exclude=exclude-from-parent.txt \\n      "$PWD"/parent/child/ \\n      "$PWD"/parent\n\n"
rsync --archive \
     --delete-after \
     --exclude=child \
     --exclude=exclude-from-child.txt \
     --exclude=exclude-from-parent.txt \
     "$PWD"/parent/child/ \
     "$PWD"/parent

tree -a --noreport -- parent; echo
# Or `find parent -type f; echo`, if you don't have `tree`

printf "%s\n\e[33mFinal comparison:\n"
printf "%s-----------------\e[39m\n"

diff --exclude=child parent parent/child; echo

輸出:

rsync version:
--------------
rsync  version 2.6.9  protocol version 29

Original state:
---------------
parent
├── delete-from-child.txt
├── exclude-from-child.txt
└── original.txt

rsync to child:
---------------
rsync --archive
     --delete-after
     --exclude=exclude-from-child.txt
     /var/www/parent/
     /var/www/parent/child

parent
├── child
│   ├── delete-from-child.txt
│   └── original.txt
├── delete-from-child.txt
├── exclude-from-child.txt
└── original.txt

Make changes:
---------------
rm parent/child/delete-from-child.txt
touch parent/child/create-in-child.txt
touch parent/child/exclude-from-parent.txt

rsync back to parent:
---------------------
rsync --archive
     --delete-after
     --exclude=child
     --exclude=exclude-from-child.txt
     --exclude=exclude-from-parent.txt
     /var/www/parent/child/
     /var/www/parent

parent
├── child
│   ├── create-in-child.txt
│   ├── exclude-from-parent.txt
│   └── original.txt
├── create-in-child.txt
├── exclude-from-child.txt
└── original.txt


Final comparison:
-----------------
Only in parent: exclude-from-child.txt
Only in parent/child: exclude-from-parent.txt

引用自:https://serverfault.com/questions/1094803