¿Mover archivos y eliminar directorios con rsync?

17

Recientemente necesitaba eliminar una gran cantidad de archivos (más de 1 millón) y lo leí haciendo:

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

Fue una de las formas más optimizadas para hacer eso, y puedo garantizar que es más rápido que rm -rf.

No soy un experto en el tema, pero, según tengo entendido, el motivo del rendimiento de rsync tiene algo que ver con la forma en que enumera los archivos (LIFO en lugar de FIFO, supongo). Ahora, el problema es que también necesito mover una gran cantidad de archivos de manera eficiente. Después de buscar un poco, encontré esto:

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

Si bien esto elimina todos los movido los archivos en ~/sourcelos directorios permanecen allí. Como tengo una estructura de directorio tipo "round-robin", el número de files/directorieses muy cercano a 1, por lo que me veo obligado a ejecutar el primer comando nuevamente para deshacerme completamente del directorio:

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

Una recta mvterminaría prácticamente al instante, pero mi ~/destinationdirectorio tiene archivos que deben mantenerse, por mvlo que no es una opción. Encontré las opciones --prune-empty-dirsy --forcersync, pero ninguna parece funcionar como lo esperaría:

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

¿Hay alguna manera de imitar un movimiento con rsync de una vez?

Alix Axel
fuente
2
Si no obtiene una respuesta aquí, intente publicar en la lista rsync. Son muy útiles lists.samba.org/mailman/listinfo/rsync
Joe
relacionado: superuser.com/questions/676671/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

7

Encontré este hilo en stackoverflow titulado: ¿ Eliminar carpetas con rsync "move"? , que hace esencialmente la misma pregunta. Una de las respuestas sugirió hacer los rsynccomandos in 2 ya que parece que no hay un solo comando que pueda realizar el movimiento / eliminación de los archivos y los directorios de origen.

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

Alternativamente, puede hacerlo usando este comando:

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

No es ideal pero hace el trabajo.

slm
fuente
Sí, fui yo quien respondió esa pregunta (y la misma "solución" también está en esta pregunta). = P
Alix Axel
@AlixAxel - Ja, lo siento, ni siquiera me di cuenta de que respondiste eso. Oh bien. ¿Debo borrar esta respuesta entonces?
slm
3
Usar rsyncpara podar directorios no se siente bien y siempre hay peligro con eso rm -rf. Recomiendo que el segundo paso sea:find source/ -d -type d -exec rmdir {} \;
loco
2
Simplemente me siento obligado a agregar, nunca usar -deletey --remove-source-filesen un solo comando rsync (los ejemplos anteriores están bien, esto es tangencial). Si interrumpe y luego vuelve a ejecutar lo que estoy describiendo, perderá los archivos transferidos. Lo que he hecho antes :(
Sridhar Sarnobat
Al limpiar find, prefiero esto: find source/ -type d -empty -delete me da una extraña sensación de tranquilidad de que no solo golpeará todo.
greyfade
10

Desde el comentario de zany hasta la respuesta de slm (¿ Mover archivos y eliminar directorios con rsync? ) Recomendaría estos 2 comandos como respuesta:

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

La ventaja es que, como dijo Zany, todavía hay algún peligro al usar rm -rf si no lo haces bien o para principiantes.

Agregué 2 opciones, -depth y -empty, y aunque no estoy seguro de si esto es realmente necesario, hace que el segundo comando sea más portátil para otras situaciones y aún más seguro (todavía hace lo correcto si algunos directorios no están vacíos y comienza a eliminar desde el punto más profundo en un árbol de directorios)

mit
fuente
¿Por qué no solo en -deletelugar de -exec rmdir {} \;?
ovejas voladoras
@flying_sheep vea el comentario de user7000 en la respuesta de sim: cuando rsync se interrumpe, podría perder archivos
mit
Cuando se interrumpe rsync, ¿el hallazgo nunca comienza o no? Por lo tanto, el borrado en una segunda rsync no debería ser un problema. Pero -delete también elimina archivos, en cambio rmdir nunca borra archivos, solo directorios. Ambos (-delete y rmdir) verifican los directorios si están vacíos antes de eliminarlos.
benba
Además las páginas man dice u debe utilizar en lugar de -execdir -exec ...
Benba
2

Esto hace el trabajo en un solo paso. Tenga en cuenta el trailing / slash / en las rutas de origen y destino.

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

Me hago eco de la advertencia de user7000 de no usar --delete y --remove-source-filesjuntos en la misma llamada a rsync. Si la operación falla o se interrumpe y se repite la misma llamada, perderá datos. Si tiene alguna duda, use la --dry-runopción para ver qué se haría.

gjvc
fuente
-ruvalParece redundante. -aes equivalente a -rlptgoD, que incluye ambos -ry -l.
greyfade