Rsync
rsync 具有自己後代的目錄
**tl; dr:**我想要
rsync
一個目錄到它自己的後代,然後rsync
將所述後代返回到原始目錄——包括兩個方向的刪除和排除。在你問一個明顯的問題之前,“你為什麼要這樣做?” 或指出另一種方法會有多好,這是業務需求。這不是我的選擇,我知道風險,所以放縱我。我不打算進一步證明這種方法的合理性。🙂
細節:
我想要
rsync
一個目錄到它自己的後代——即,一個“下面”或“裡面”的目錄,例如parent
,parent/child
然後將後代的更改同步回原始目錄,例如,parent/child
toparent
,包括刪除和兩個方向的排除。在視覺上,我需要這樣做:parent -> parent/child parent <- parent/child
困難在於…
- 從祖先到後代時防止無限遞歸
- 將後代同步回其祖先時,不會在操作中刪除源文件(表現為“文件已消失”錯誤)
- 始終尊重例外情況
解決方案分為三個部分。為了…
- 排除相對於祖先的後代目錄路徑,例如,
child
從同步時parent/child
- 使用
--delete-after
標誌而不是--delete
- 使所有排除路徑都相對於源,例如,
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