¿Cómo compara dos carpetas y copia la diferencia en una tercera carpeta?

23

Tienes tres carpetas:

  • carpeta actual , que contiene sus archivos actuales
  • carpeta antigua , que contiene una versión anterior de los mismos archivos
  • diferencia de carpeta , que es solo una carpeta vacía

¿Cómo se compara vieja con la corriente y copiar los archivos que son diferentes (o enteramente nuevo) en la corriente de diferencia ?


He buscado por todos lados y parece algo sencillo de abordar, pero no puedo hacer que funcione en mi ejemplo particular. La mayoría de las fuentes sugirieron el uso de rsync, así que terminé con el siguiente comando:

rsync -ac --compare-dest=../old/ new/ difference/

Sin embargo, lo que esto hace es copiar todos los archivos de nuevo a diferencia , incluso aquellos que son los mismos que en el anterior .

En caso de que ayude (tal vez el comando está bien y la falla se encuentra en otro lugar), así es como probé esto:

  1. Hice las tres carpetas.
  2. Hice varios archivos de texto con diferentes contenidos en la antigüedad .
  3. Copié los archivos de viejo a nuevo .
  4. Cambié el contenido de algunos de los archivos en nuevo y agregué algunos archivos adicionales.
  5. Ejecuté el comando anterior y verifiqué los resultados en diferencia .

He estado buscando una solución durante los últimos días y realmente agradecería algo de ayuda. No necesariamente tiene que estar usando rsync, pero me gustaría saber qué estoy haciendo mal si es posible.

Thane
fuente
posible duplicado de ¿Cómo guardo los archivos modificados?
wingedsubmariner
@wingedsubmariner No creo que sea un duplicado, ya que la respuesta aceptada en la pregunta vinculada es el comando sobre el cual el OP está haciendo una pregunta.
Bernhard
@Bernhard Ah, mi mal. Supongo que no entendí la pregunta original.
wingedsubmariner
@wingedsubmariner No te preocupes, dijiste "posible", y estoy de acuerdo en que se ve muy similar :)
Bernhard

Respuestas:

7

No estoy seguro de si puede hacerlo con cualquier comando de Linux existente como rsync o diff. Pero en mi caso tuve que escribir mi propio script usando Python, ya que python tiene el módulo "filecmp" para la comparación de archivos. He publicado todo el script y el uso en mi sitio personal: http://linuxfreelancer.com/

Su uso es simple: déle la ruta absoluta del nuevo directorio, el directorio antiguo y el directorio de diferencias en ese orden.

#!/usr/bin/env python

import os, sys
import filecmp
import re
from distutils import dir_util
import shutil
holderlist=[]

def compareme(dir1, dir2):
    dircomp=filecmp.dircmp(dir1,dir2)
    only_in_one=dircomp.left_only
    diff_in_one=dircomp.diff_files
    dirpath=os.path.abspath(dir1)
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in only_in_one]
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in diff_in_one]
    if len(dircomp.common_dirs) > 0:
        for item in dircomp.common_dirs:
            compareme(os.path.abspath(os.path.join(dir1,item)), os.path.abspath(os.path.join(dir2,item)))
        return holderlist

def main():
 if len(sys.argv) > 3:
   dir1=sys.argv[1]
   dir2=sys.argv[2]
   dir3=sys.argv[3]
 else:
   print "Usage: ", sys.argv[0], "currentdir olddir difference"
   sys.exit(1)

 if not dir3.endswith('/'): dir3=dir3+'/'

 source_files=compareme(dir1,dir2)
 dir1=os.path.abspath(dir1)
 dir3=os.path.abspath(dir3)
 destination_files=[]
 new_dirs_create=[]
 for item in source_files:
   destination_files.append(re.sub(dir1, dir3, item) )
 for item in destination_files:
  new_dirs_create.append(os.path.split(item)[0])
 for mydir in set(new_dirs_create):
   if not os.path.exists(mydir): os.makedirs(mydir)
#copy pair
 copy_pair=zip(source_files,destination_files)
 for item in copy_pair:
   if os.path.isfile(item[0]):
    shutil.copyfile(item[0], item[1])

if __name__ == '__main__':
 main()
Daniel t.
fuente
21

He descubierto cuál era el problema en mi caso:

Los archivos que estaba comparando tenían diferentes marcas de tiempo. Supongo que no debería haber usado el argumento -a porque rsync estaba tratando de preservar las marcas de tiempo al copiar archivos. El comando que funcionó para mí fue:

rsync -rvcm --compare-dest=../old/ new/ difference/
Thane
fuente
Creo que para probar esto con la opción -a (archivo), debería haber usado rsync -apara "copiar" los archivos inicialmente (o el equivalente de cp), luego eliminarlos o modificarlos. (Me gusta seguir con rsync porque sé que es coherente sin pensar en lo que podría estar haciendo). Creo que debería haber funcionado con el comando original. La opción -a incluye -t (comparar por marca de tiempo), que es la alternativa a -c (comparar por suma de verificación).
sabio
2
En mi opinión, esta respuesta debería ser la aceptada, ya que es mucho más simple. Además, el comando solo funcionó para mí cuando proporcioné la ruta completa para old/y new/.
Yamaneko el
La advertencia parece ser que el destino de comparación debe ser el camino relativo a la diferencia como se ve desde dentro del destino real
Ryan Williams
1

Esto podría ayudar a algunos lectores: en Windows, un pequeño y antiguo programa gratuito, Third Dir, hace exactamente lo que se pide aquí. Ya no está disponible a través del desarrollador, Robert Vašíček. Pero estoy seguro de que se puede encontrar a través de algunos repositorios en línea.

Aquí está la descripción del desarrollador, que permanece en su sitio:

Tercer directorio: un sincronizador de directorio inusual: los diferentes archivos se copian en el tercer directorio. Es muy útil extraer, por ejemplo, fotos nuevas o editadas de un gran árbol de directorios en un disco fijo a una carpeta temporal, luego agregarlas al CD de archivo (nota: los archivos originales se comparan con el CD). Versión 1.4, tamaño 23kB. Creado 2005-02-12.

Historia: Versión 1.14: más eficiente cuando se comparan muchos decenas de miles de archivos.

Steve
fuente
0

La forma rsync dada por Thane con las adiciones de Yamaneko funciona muy bien pero deja directorios vacíos. Para mí, la solución final fue en dos pasos, primero llamar a rsync con la ruta completa, luego un comando de búsqueda para eliminar todos los directorios vacíos:

rsync -rvcm --compare-dest=/tmp/org/ /tmp/new/ /tmp/difference/
find /tmp/difference/ -d -type d -empty -exec rmdir {} \; -print

Tenga en cuenta que incluso con la opción --links, rsync no mantuvo enlaces simbólicos, sino que copió los datos de destino.

PierreL
fuente
Tenga en cuenta que en lugar de -empty -exec rmdir {} \;usted puede usar -empty -delete.
mivk
-3

Yo uso el dualpane XY Explorer (comercial), que puede hacer muchos trucos y este es uno de ellos. Abrir Currenten un panel y Viejo en el otro. Activa el panel Actual. Vaya a Paneles > Selección de sincronización . Te da 5 opciones para seleccionar:

  1. Partidos (listados en ambos)
  2. Uniques (en el panel activo)
  3. Más nuevo (en el panel activo)
  4. Archivos únicos y más nuevos (en el panel activo)
  5. Seleccionado (los seleccionados en el otro panel)

Ahora puede copiar la selección resultante desde Currentdonde desee. Lo usé para comparar las mailfoldersinstalaciones antiguas con las más recientes. La estructura de carpetas era bastante compleja, pero (casi) todas mbs-filestenían un número único.

Así que hice una búsqueda mbs-filesen la raíz anterior mailfolder(en un panel), así como en la más nueva (en el otro panel) e hice una comparación en los resultados de búsqueda en cada panel ( Sync Select Unique , para encontrar los correos que se perdieron durante reinstala)! También puedes configurar muchas opciones.

Martijn Douwes
fuente
1
Si está hablando de software no estándar, debe incluir un enlace. Si te refieres a XYplorer, eso no va a ayudar al OP en absoluto.
Anthon