RSYNC no elimina directorios de origen

27

Estoy usando rsync para recuperar archivos esenciales de un servidor, luego elimino los archivos del servidor una vez que los tengo localmente. El comando completo que estoy ejecutando está debajo.

Esto elimina con éxito los archivos en el servidor de origen, sin embargo, todavía quedan directorios vacíos. No recibo ningún mensaje o error. Toda la salida es normal. Quizás esta sea la funcionalidad prevista.

¿Cómo puedo decirle a rsync que limpie todo, incluidos los directorios?

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

La versión es 3.0.9 en ambos extremos.

Sajan Parikh
fuente
Relacionado: unix.stackexchange.com/questions/78375/… | serverfault.com/questions/384110/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

13

El comportamiento --remove-source-filesque observa es exactamente el 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.

No hay un comando específico para eliminar los directorios, ya que estas dos discusiones en StackExchange y ServerFault se muestran claramente. La solución sugerida es emitir dos comandos separados:

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

La última parte del comando sugerido en estas dos publicaciones,

 rmdir source/

que se necesita para eliminar el directorio fuente (ahora vaciado) tiene este formulario en estas publicaciones porque los OP y las respuestas están usando rsync para mover grandes cantidades de archivos dentro de la misma máquina. En su caso, tendrá que hacer esto manualmente.

MariusMatutiae
fuente
55
La rsync --deletesugerencia es peligrosa porque ignora la posibilidad de que rsync no se haya completado o que haya nuevos archivos en la fuente. El findsiguiente método de @ slhck es mucho más seguro.
Sai
29

La página de manual incluso dice:

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

Si desea eliminar directorios vacíos en su fuente, si aún quedan archivos, haga lo siguiente:

find . -depth -type d -empty -delete

Pero para un directorio raíz vacío, una rm -rf <directory>voluntad será suficiente.

slhck
fuente
55
Sí, esta es la única solución. es una característica tonta que falta en rsync ... rsync sabe cuándo se procesó el último archivo en un directorio ... también es bastante fácil eliminar el directorio si está vacío.
Erik Aronesty
44
Tenga en cuenta que emitir "rm -rf" es propenso a las condiciones de carrera y lo desaliento.
Raúl Salinas-Monteagudo
Variante que no borra el directorio vacío de nivel superior:find some_dir -depth -type d -empty -not -path some_dir -delete
Cameron Tacklind
5

El uso de " rm -rf " tiene una condición de carrera inherente, es decir, puede eliminar archivos que acaban de crearse entre las invocaciones rsync y rm .

Prefiero usar:

rsync --remove-source-files -a server: entrante / entrante / &&

servidor ssh encuentra entrante -tipo d -delete

Esto NO eliminará los directorios si no están vacíos.

Raúl Salinas-Monteagudo
fuente
2
El rm -rftambién eliminará los archivos que no fueron transferidos por alguna razón.
Kristian
1
Esta respuesta pierde la -depthopción que indica findprocesar en el orden correcto. Como resultado de este error, los directorios que contienen solo directorios vacíos (posiblemente de forma recursiva) no se eliminarán. La variante de @slhck tiene razón.
Stéphane Gourichon
1

-m, --prune-empty-dirs pode cadenas de directorios vacías de la lista de archivos

--force forzar la eliminación de directorios incluso si no está vacío

MarcoP
fuente
1
Eso solo evita que rsync copie directorios vacíos. No elimina directorios vacíos.
Navin
1

Elimine los archivos de origen, luego elimine los directorios para estar seguro.

# 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;

Más sobre GNU Paralelo

Daniel Andrei Mincă
fuente