Mover arquivos e excluir diretórios com o rsync?


17

Recentemente, precisei excluir um grande número de arquivos (mais de 1 milhão) e li isso fazendo:

rsync -av --delete `mktemp -d`/ ~/source && rmdir ~/source

Foi uma das maneiras mais otimizadas de fazer isso, e posso garantir que é mais rápido que rm -rf.

Eu não sou um especialista no assunto, mas, pelo meu entendimento, a razão do desempenho do rsync tem algo a ver com a maneira como lista os arquivos (LIFO em vez de FIFO, suponho). Agora, o problema é que também preciso mover um grande número de arquivos de maneira eficiente. Depois de pesquisar um pouco, achei o seguinte:

rsync -av --ignore-existing --remove-source-files ~/source ~/destination

Enquanto isso exclui todos os movidos arquivos em ~/source, os diretórios permanecem lá. Como eu tenho uma estrutura de diretório do tipo "round-robin", o número de files/directoriesé muito próximo de 1, então sou forçado a executar o primeiro comando novamente para livrar-me completamente do diretório:

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

Uma sequência mvterminaria virtualmente instantaneamente, mas meu ~/destinationdiretório possui arquivos que devem ser mantidos, portanto mvnão é uma opção. Encontrei as opções --prune-empty-dirse --forcersync, mas nenhuma parece funcionar como eu esperava:

--force                 force deletion of directories even if not empty
--prune-empty-dirs      prune empty directory chains from the file-list
--remove-source-files   sender removes synchronized files (non-dirs)

Existe uma maneira de imitar uma jogada com o rsync de uma só vez?


2
Se você não receber uma resposta aqui, tente postar na lista rsync. Eles são muito úteis. lists.samba.org/mailman/listinfo/rsync
Joe

Respostas:


7

Encontrei este tópico no stackoverflow intitulado: Excluindo pastas com o rsync "move"? , que está fazendo essencialmente a mesma pergunta. Uma das respostas sugeriu a rsyncexecução dos comandos in 2, pois parece que não há um único comando que possa realizar a movimentação / remoção dos arquivos e dos diretórios de origem.

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

Como alternativa, você pode fazer isso usando este comando:

$ rsync -axvvES --remove-source-files source_directory /destination/ && \
  rm -rf source_directory

Não é o ideal, mas faz o trabalho.


Sim, fui eu quem respondeu a essa pergunta (e a mesma "solução" também está nessa questão). = P
Alix Axel

@AlixAxel - Ah, desculpe, eu nem percebi que você respondeu essa. Ah bem. Devo excluir esta resposta então?
slm

3
Usar rsyncpara remover diretórios não parece certo e sempre há perigo rm -rf. Eu recomendo o 2º passo de ser:find source/ -d -type d -exec rmdir {} \;
zany

2
Apenas me sinto obrigado a adicionar, nunca usar -deletee --remove-source-filesem um único comando rsync (os exemplos acima são bons, isso é tangencial). Se você interromper e executar novamente o que estou descrevendo, você perderá os arquivos transferidos. O que eu fiz antes :(
Sridhar Sarnobat

Ao limpar find, prefiro o seguinte: find source/ -type d -empty -delete isso me dá uma estranha sensação de segurança de que isso não vai prejudicar tudo.
Greyfade 5/04

10

Do comentário de zany à resposta do slm ( Mover arquivos e excluir diretórios com o rsync? ) Eu recomendaria estes 2 comandos como resposta:

rsync -av --ignore-existing --remove-source-files source/ destination/ && \
find source/ -depth -type d  -empty -exec rmdir "{}" \;

A vantagem é que, como Zany disse, ainda há algum perigo envolvido no uso de rm -rf se você não acertar ou para iniciantes.

Adicionei 2 opções, -thth e -vazty e, embora não tenha certeza se isso é realmente necessário, ele torna o segundo comando mais portátil para outras situações e ainda mais seguro (ainda faz a coisa certa se alguns diretórios não estiverem vazios e começa a remover do ponto mais profundo de uma árvore de diretórios)


por que não apenas em -deletevez de -exec rmdir {} \;?
ovelha voadora

@flying_sheep veja o comentário de user7000 na resposta do sim: quando o rsync é interrompido, você pode perder arquivos
mit

Quando o rsync é interrompido, a descoberta nunca começa ou não? Portanto, o -delete em um segundo rsync não deve ser um problema. Mas -delete também remove arquivos; em vez disso, o rmdir nunca exclui arquivos, apenas diretórios. Ambos (-delete e rmdir) verificam os diretórios se estiverem vazios antes de excluir.
Benba

Além disso, as páginas man diz u deve usar -execdir em vez de exec ...
Benba

2

Isso faz o trabalho em uma etapa. Observe a trilha / barra / nos caminhos de origem e destino.

rsync \
    -ruval \
    --ignore-existing \
    --remove-source-files \
    --prune-empty-dirs \ 
    /source/path/ /target/path/

Repito a advertência do user7000 de não usar --deletee --remove-source-filesjuntos na mesma chamada para rsync. Se a operação falhar ou for interrompida e a mesma chamada for repetida, você perderá dados. Em caso de dúvida, use a --dry-runopção para ver o que seria feito.


-ruvalparece redundante. -aé equivalente a -rlptgoD, que inclui ambos -re -l.
Greyfade 28/05
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.