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?

Alix Axel
fonte
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
related: superuser.com/questions/676671/…
Ciro Santilli escreveu:

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.

slm
fonte
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)

mit
fonte
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.

gjvc
fonte
-ruvalparece redundante. -aé equivalente a -rlptgoD, que inclui ambos -re -l.
Greyfade 28/05