rsync compara directorios?


63

¿Es posible comparar dos directorios con rsync y solo imprimir las diferencias? Hay una opción de ejecución en seco, pero cuando aumento la verbosidad a un cierto nivel, se muestran todos los archivos comparados.

ls -alRy diffno es una opción aquí, ya que hay enlaces duros en la fuente que hacen que cada línea sea diferente. (Por supuesto, podría eliminar esta columna con perl).


Respuestas:


46

Probablemente tendrá que ejecutar algo parecido rsync -avun --deleteen ambas direcciones.

Pero, ¿qué estás tratando de lograr realmente?

Actualización :

rsync -avun --delete $TARGET $SOURCE |grep "^deleting " le dará una lista de archivos que no existen en el directorio de destino.

"grep delet" porque cada línea imprime: delet ing ..file ..

rsync -avun $SOURCE $TARGET le dará una lista de archivos "diferentes" (incluidos los archivos nuevos).


49

Para agregar a la respuesta de Nils (para cualquiera que se encuentre con esto a través de Google), por defecto rsyncsolo compara los tamaños de archivo y los tiempos de modificación para saber si hay alguna diferencia. (Si son diferentes, hace más, pero si son iguales, se detiene allí).

Si desea comparar el contenido real del archivo , incluso para archivos que tienen el mismo tamaño y la última hora de modificación, agregue la bandera -cpara indicar rsyncque compare los archivos usando una suma de verificación.

rsync -avnc $SOURCE $TARGET

(La -uopción le dice a rsync para ignorar los archivos que son nuevos en $TARGETque en $SOURCEque es probable que no desee si está comparando su contenido.)


66
Si solo le importa que los datos sean los mismos, es posible que desee agregar --no-group --no-owner --no-perms --no-timeso una combinación de estos según sus necesidades.
flungo

1
@flungo, o simplemente use un subconjunto de las opciones implícitas en -alugar de -a, por ejemplorsync -rlDcnv --delete $SOURCE $TARGET
maxschlepzig

Agregue --deletea la lista los archivos que solo existen en$TARGET
Tom Hale

25

Solo para aquellos menos familiarizados con rsync:

rsync -rvnc --delete ${SOURCE}/ ${DEST}
  • -n: bit más importante: no cambie nada;
  • -rc: compare solo los contenidos (de lo contrario, use -ac);
  • -v : enumerar los archivos)
  • --delete : busque una diferencia simétrica, no unidireccional.
  • Finalmente, /significa "mirar dentro del directorio y comparar su contenido con el destino".

Imprimirá una rsyncsalida habitual ,

  • con un <nombre de archivo> en una línea para cada archivo "nuevo" en${SOURCE}
  • y una línea de "eliminación de <nombre de archivo>" para cada archivo "nuevo" en ${DEST}.

  • También puede imprimir algunas advertencias, como "omitir el archivo no regular <nombre de archivo>" para enlaces simbólicos.

PD. Sé que es un PS terrible, pero de hecho se agregó rápidamente. Sin embargo, apuesto a que uno puede encontrar esto útil.


PPS Alternativamente, uno también podría hacer

find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST   -type f -exec md5sum {} \; | tee dest.md5

Si los nombres de archivo no contienen nuevas líneas, podemos ordenar ambos *.md5archivos y diffellos. (Sin embargo, esto solo funcionará para archivos; es decir, no se detectará un directorio vacío a ambos lados).


16

Sorprendentemente, ninguna respuesta en 6 años usa la -iopción o da una buena salida, así que aquí voy:

TLDR - Solo muéstrame los comandos

rsync -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L             /'
rsync -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R             /'
rsync -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'

Comprender la salida

Aquí hay un ejemplo de la salida:

L             file-only-in-Left-dir
R             file-only-in-right-dir
X >f.st...... file-with-dif-size-and-time
X .f...p..... file-with-dif-perms

Tenga en cuenta el primer carácter de cada línea:

  • L/ Rsignifica que el archivo / dir aparece solo en el directorio Left o Right.
  • Xsignifica que el archivo aparece en ambos lados, pero no es lo mismo (en cuyo caso los próximos 11 caracteres que dan más información. s, ty pmuestran diferencias en s ize, t iempo y p ermissions respectivamente - para obtener más información tratar man rsyncy buscar --itemize-changes) .

Opciones adicionales que puede desear usar

Si desea comparar también el propietario / grupo / permisos de los archivos, agregue las opciones -o/ -g/ -prespectivamente. Finalmente, tenga en cuenta que, de manera predeterminada, rsync considera que dos archivos son iguales si tienen el mismo nombre, hora y tamaño. Esto es extremadamente rápido y la mayoría de las veces es más que suficiente, pero si desea estar 100% seguro, agregue -ctambién para comparar el contenido de los archivos con el mismo nombre, hora y tamaño.

TLDR: solo dame un script para llamar

Aquí está. Llámalo así

diff-dirs Left_Dir Right_Dir [options]

Todas las opciones mencionadas anteriormente en la sección "Opciones adicionales que quizás desee utilizar" también se aplican aquí.

#!/bin/bash
# Compare two directories using rsync and print the differences
# CAUTION: options MUST appear after the directories
#
# SYNTAX
#---------
# diff-dirs Left_Dir Right_Dir [options]
#
# EXAMPLE OF OUTPUT
#------------------
# L             file-only-in-Left-dir
# R             file-only-in-right-dir
# X >f.st...... file-with-dif-size-and-time
# X .f...p..... file-with-dif-perms
#
# L / R mean that the file/dir appears only at the `L`eft or `R`ight dir. 
#
# X     means that a file appears on both sides but is not the same (in which
#       case the next 11 characters give you more info. In most cases knowing
#       that s,t,T and p depict differences in Size, Time and Permissions 
#       is enough but `man rsync` has more info
#       (look at the --itemize-changes option)
#
# OPTIONS
#---------
# All options are passed to rsync. Here are the most useful for the purpose
# of directory comparisons:
#
# -c will force comparison of file contents (otherwise only
#    time & size is compared which is much faster)
#
# -p/-o/-g will force comparison of permissions/owner/group

if [[ -z $2 ]] ; then
    echo "USAGE: $0 dir1 dir2 [optional rsync arguments]"
    exit 1
fi

set -e

LEFT_DIR=$1; shift
RIGHT_DIR=$1; shift
OPTIONS="$*"

# Files that don't exist in Right_Dir
rsync $OPTIONS -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L             /'
# Files that don't exist in Left_Dir
rsync $OPTIONS -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R             /'
# Files that exist in both dirs but have differences
rsync $OPTIONS -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'

¿Como funciona?

Estamos llamando a rsync así:

rsync -rin ...

Usamos -i( --itemize-changes) para decirle a rsync que imprima una línea de salida para cada archivo que contiene información sobre cualquier diferencia entre los dos directorios. Necesitamos -nsuprimir el comportamiento normal de rsync (que es intentar sincronizar los dos directorios copiando / eliminando archivos). También necesitamos -rtrabajar recursivamente para todos los archivos / subdirectorios.

Llamamos a rsync tres veces:

Primera llamada : imprimir archivos que no existen en Dir_B. Necesitamos usar --ignore-existingpara ignorar los archivos que existen en ambos lados.

rsync -rin --ignore-existing $DIR_A/ $DIR_B/

2da llamada : exactamente como antes pero intercambiamos el orden de DIR_A / DIR_B.

3ra llamada : Finalmente, usamos --existingpara verificar solo los archivos que aparecen en ambos directorios.

rsync -rin --existing $DIR_A/ $DIR_B/

No sé sobre los demás, pero estoy usando tu guión. ¡Buen trabajo! gracias
Marinaio

Muchas gracias! Necesitaba algunos ajustes, los compartiré a continuación en caso de que alguien esté buscando algo similar. Primero, quería ejecutar rsync remoto como sudo user, para eso agregué --rsync-path="sudo rsync"a cada comando rsync. En segundo lugar, quería comparar el directorio local con el directorio remoto. Agregué --rsh "ssh -p1234"porque en mi caso SSH se está ejecutando en el puerto 1234. Luego llamé a script como diff-dirs user@111.11.1.1:/mnt/Vol1/dir1/ /localMnt/dir1 -c.
sen4ik

7

Según su pregunta, entiendo que no desea usar diff en ls , pero también puede usar diff de forma recursiva en los directorios:

diff -rq DIR1 DIR2

2

Me tomó algunos intentos para que esto funcione. La respuesta de Nils requiere que $TARGETtermine en un final /, como se explica por ジ ョ ー ジ.

Aquí hay una versión que agrega explícitamente el final /:

rsync -avun --delete ${TARGET}/ ${SOURCE}  | sed -ne 's/^deleting *//p'

Esto proporciona la lista de archivos que existen debajo del ${SOURCE}directorio pero no debajo del ${TARGET}directorio.

Utilizo sedaquí para eliminar el inicio deletingde las líneas de salida y para imprimir solo esas líneas.

No uso la rsyncopción -cporque comparar el contenido del archivo sería mucho más lento para mis casos de uso, y comparar solo los tamaños de archivo y los tiempos de modificación también parece suficiente en estos casos. No tengo ninguna razón para sospechar que mis computadoras sufren problemas de distorsión del reloj o que algo cambió maliciosamente las marcas de tiempo. Además, el resultado de -cno puede cambiar la decisión de eliminar un archivo, solo la decisión de actualizar o mantener un archivo.

También uso -uy -a(en lugar de-r ), para que luego pueda reutilizar la línea de comando y cambiarla para copiar los directorios y archivos seleccionados de ${SOURCE}a ${TARGET}, de esta manera:

rsync -avu ${SOURCE}/{dirA,dirB,fileX} ${TARGET}   # copy some files

0

Tengo otra idea de hacer esto:

rsync -rn --out-format=FILEDETAIL::%n  $TARGET $SOURCE  | grep "^FILEDETAIL"

Puede hacer coincidir "FILEDETAIL ::" con la salida del comando. Además, puede cambiar la cadena "FILEDETAIL ::". El "% n" es el nombre del archivo.

-r Esto le dice a rsync que copie directorios recursivamente.

-n Esto hace que rsync realice una ejecución de prueba que no realiza ningún cambio.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.