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

相关内容