Como fazer com que o rsync exclua diretórios do destino que não estão na lista de origem

Como fazer com que o rsync exclua diretórios do destino que não estão na lista de origem

Quero poder sincronizar arquivos de vários diretórios para um diretório. Se eu remover um diretório da lista de origem, quero que esse diretório e todos os seus arquivos sejam removidos do destino.

Aqui está um exemplo rápido:

mkdir dir1
touch dir1/file1
mkdir dir2
touch dir2/file2
mkdir dir3
rsync -a dir1 dir2 dir3

dir3 agora contém "dir1/arquivo1" e "dir2/arquivo2".

Se eu sincronizar novamente e remover dir2 da lista:

rsync -a dir1 dir3

Então eu gostaria que dir2/file2 e dir2 fossem removidos do destino.

A opção --delete para rsync lida apenas com exclusões entre dir1 e dir3/dir1, então dir2 permanece (mesmo se estiver usando --delete).

Examinei as várias opções na página de manual do rsync e não vejo nenhuma opção que diga ao rsync para "combinar" todas as fontes e considerá-las como "uma" árvore para que "--delete" funcione o que eu quero que faça. No entanto, estou bastante confiante de que não sou a primeira pessoa a querer fazer algo assim.

Ideias?

Responder1

Obviamente, o --deletesinalizador não funciona se você sincronizar vários diretórios de origem com um diretório de destino. Em vez de sincronizar dir1e dir2você dir3pode sincronizar o conteúdo do diretório pai de dir1e dir2.

Exemplo (usando sinalizador rsync -ipara ver as alterações):

$ mkdir -p dir12/dir1 dir12/dir2 dir3
$ touch dir12/dir1/file1 dir12/dir2/file2
$ rsync -ai dir12/ dir3
cd+++++++++ dir1/
>f+++++++++ dir1/file1
cd+++++++++ dir2/
>f+++++++++ dir2/file2
# BEFORE: dir1 and dir2 were synced to dir3
$ rm -rf dir12/dir2
$ rsync -ai --delete dir12/ dir3
*deleting   dir2/file2
*deleting   dir2/
.d..t...... ./
# AFTER: dir3/dir2 is gone

Se você não tiver um diretório pai comum, dir12/dir2poderá haver um link simbólico apontando para o diretório real. Com a opção -L( --copy-links) na primeira rsyncchamada, você obteria a mesma estrutura de diretório dir3do dir2diretório (em vez de um link simbólico). E depois de excluir o link simbólico dir12/dir2e sincronizar novamente com --deleteo diretório dir3/dir2, desapareceria como no exemplo.

EDITAR:

Eu brinquei um pouco e posso ter encontrado um hack:

$ mkdir empty dir1 dir2 dir3
$ touch dir1/file1 dir2/file2
$ rsync -ai dir1 dir2 dir3
cd+++++++++ dir1/
>f+++++++++ dir1/file1
cd+++++++++ dir2/
>f+++++++++ dir2/file2
$ rsync -ai --delete empty/ dir1 dir3
*deleting   dir2/file2
*deleting   dir2/
.d..t...... ./

Use empty/como espaço reservado para todos os diretórios que você deseja excluir.

informação relacionada