O RSYNC não exclui diretórios de origem

27

Estou usando o rsync para buscar arquivos essenciais de um servidor e exclua os arquivos do servidor assim que os tiver localmente. O comando completo que estou executando está abaixo.

Isso exclui com êxito os arquivos no servidor de origem, no entanto, os diretórios vazios ainda permanecem. Não recebo nenhuma mensagem ou erro. Toda a saída é normal. Talvez esta seja a funcionalidade pretendida.

Como posso dizer ao rsync para limpar tudo, incluindo os diretórios?

rsync --progress -vrzh --remove-source-files

A versão é 3.0.9 em ambas as extremidades.

Sajan Parikh
fonte

Respostas:

13

O comportamento --remove-source-filesque você observa é exatamente o especificado por man rsync:

--remove-source-files

   This tells rsync to remove from the sending side the files (meaning non-directories) that are a part of the transfer and have been successfully duplicated on the receiving side.

Não há um comando específico para remover os diretórios, como essas duas discussões no StackExchange e ServerFault mostram claramente. A solução sugerida é emitir dois comandos separados:

 rsync -av --ignore-existing --remove-source-files source/ destination/ && \
 rsync -av --delete `mktemp -d`/ source/ 

A última parte do comando sugerida nessas duas postagens,

 rmdir source/

o que é necessário para remover o diretório de origem (agora esvaziado) tem esse formato nessas postagens porque os OPs e as respostas estão usando o rsync para mover grandes quantidades de arquivos na mesma máquina. No seu caso, você terá que fazer isso manualmente.

MariusMatutiae
fonte
5
A rsync --deletesugestão é perigosa, porque ignora a possibilidade de que o rsync não tenha sido concluído ou que haja novos arquivos na fonte. O findmétodo do @ slhck abaixo é muito mais seguro.
Sai
29

A página de manual ainda diz:

--remove-source-files   sender removes synchronized files (non-dirs)

Se você deseja remover diretórios vazios em sua fonte, se ainda houver arquivos, faça o seguinte:

find . -depth -type d -empty -delete

Mas para um diretório raiz vazio, uma rm -rf <directory>vontade é suficiente.

slhck
fonte
5
Sim, esta é a única solução. é uma espécie de recurso bobo ausente do rsync ... o rsync sabe quando é processado o último arquivo em um diretório ... é fácil remover o diretório também, se estiver vazio.
Erik Aronesty
4
Cuidado que emitir "rm -rf" é propenso a condições de corrida e eu o desencorajo.
Raúl Salinas-Monteagudo
Variante que não apaga o diretório vazio de nível superior:find some_dir -depth -type d -empty -not -path some_dir -delete
Cameron Tacklind
5

O uso de " rm -rf " tem uma condição de corrida inerente, você pode excluir os arquivos que foram criados entre as invocações rsync e rm .

Eu prefiro usar:

rsync --remove-source-files -um servidor: entrada / entrada / &&

servidor ssh encontrar -type d -delete de entrada

Isso NÃO removerá os diretórios se eles não estiverem vazios.

Raúl Salinas-Monteagudo
fonte
2
O rm -rftambém irá remover arquivos que não foram transferidos por algum motivo.
21816 Kristian
1
Esta resposta perde a -depthopção que instrui finda processar na ordem correta. Como resultado dessa falha, os diretórios que contêm apenas diretórios vazios (possivelmente recursivamente) não serão excluídos. A variante de @slhck está correta.
Stéphane Gourichon
1

-m, --prune-empty-dirs podar cadeias de diretórios vazias da lista de arquivos

--force forçar a exclusão de diretórios, mesmo se não estiver vazio

MarcoP
fonte
1
Isso apenas impede que o rsync copie dirs vazios. Não exclui dirs vazios.
Navin
1

Remova os arquivos de origem e remova os diretórios para garantir a segurança.

# given this scenario where you generate folders 2014-01-01 etc.. that have an archive myfile.tar.gz
pushd $(mktemp -d)
mkdir 201{4..6}-{01..12}-{01..31}
for i in $(ls); do; touch $i/myfile.tar.gz;done;
# find and rsync on 10 CPU threads directories that match ./2015-*
find /tmp/tmp.yjDyF1jN70/src -type d -name '2015-*' | \
parallel \
--jobs 10 \
--progress \
--eta \
--round-robin \
rsync \
--hard-links \
--archive --verbose --protect-args \
--remove-source-files \
{} /tmp/tmp.yjDyF1jN70/dest
# now safely remove empty directories only
for i in $(ls /tmp/tmp.yjDyF1jN70/src); do; rmdir /tmp/tmp.yjDyF1jN70/src/$i; done;

Mais sobre o GNU Parallel

Daniel Andrei Mincă
fonte