Cómo comparar archivos con el mismo nombre en dos directorios diferentes usando un script de shell

StackOverflow https://stackoverflow.com/questions/119788

  •  02-07-2019
  •  | 
  •  

Pregunta

Antes de pasar a usar SVN, solía administrar mi proyecto simplemente manteniendo un /develop/ directorio y editar y probar archivos allí, luego moverlos al /main/ directorio.Cuando decidí pasar a SVN, necesitaba estar seguro de que los directorios estaban realmente sincronizados.

Entonces, ¿cuál es una buena manera de escribir un script de shell [bash] para comparar recursivamente archivos con el mismo nombre en dos directorios diferentes?

Nota:Los nombres de directorio utilizados anteriormente son solo para muestra.No recomiendo almacenar su código en el nivel superior :).

¿Fue útil?

Solución

El comando diff tiene una opción -r para comparar directorios de forma recursiva:

diff -r /develop /main

Otros consejos

diff -rqu /develop /main

De esa manera solo te dará un resumen de los cambios :)

Si quieres ver solo nuevo/faltante archivos

diff -rqu /develop /main | grep "^Only

Si quieres dejarlos desnudos:

diff -rqu /develop /main | sed -rn "/^Only/s/^Only in (.+?): /\1/p"

La diferencia que tengo disponible permite diferencias recursivas:

diff -r main develop

Pero con un script de shell:

( cd main ; find . -type f -exec diff {} ../develop/{} ';' )

[Leí en alguna parte que responder tus propias preguntas está bien, así que ahí va :)]

Probé esto y funcionó bastante bien.

[/]$ cd /develop/
[/develop/]$ find | while read line; do diff -ruN "/main/$line" $line; done |less

Puede optar por comparar solo archivos específicos [por ejemplo, solo los .php] editando la línea anterior como

[/]$ cd /develop/
[/develop/]$ find -name "*.php" | while read line; do diff -ruN "/main/$line" $line; done |less

¿Alguna otra idea?

aquí hay un ejemplo de un script mío (algo desordenado), dircompare.sh, que lo hará:

  • ordenar archivos y directorios en matrices dependiendo del directorio en el que se encuentren (o ambos), en dos pasadas recursivas
  • Los archivos que se encuentran en ambos directorios, se ordenan nuevamente en dos matrices, dependiendo de si diff -q determina si difieren o no
  • para aquellos archivos que diff los reclamos son iguales, muestra y compara marcas de tiempo

Espero que pueda resultar útil. ¡Salud!

EDITAR2:(En realidad, funciona bien con archivos remotos: el problema fue la señal Ctrl-C no controlada durante una operación de diferenciación entre el archivo local y remoto, lo que puede llevar un tiempo;El script ahora se actualizó con una trampa para manejar eso; sin embargo, se deja la edición anterior a continuación como referencia.):

EDITAR:...excepto que parece bloquear mi servidor para un directorio ssh remoto (que intenté usar durante ~/.gvfs)...Entonces esto no es bash ya, pero supongo que una alternativa es usar rsync, aquí tienes un ejemplo:

$ # get example revision 4527 as testdir1
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@4527 testdir1

$ # get earlier example revision 2729 as testdir2
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@2729 testdir2

$ # use rsync to generate a list 
$ rsync -ivr --times --cvs-exclude --dry-run testdir1/ testdir2/
sending incremental file list
.d..t...... ./
>f.st...... CMakeLists.txt
>f.st...... MACCS.txt
>f..t...... SMARTS_InteLigand.txt
...
>f.st...... atomtyp.txt
>f+++++++++ babel_povray3.inc
>f.st...... bin2hex.pl
>f.st...... bondtyp.h
>f..t...... bondtyp.txt
...

Tenga en cuenta que:

  • Para obtener lo anterior, no debes olvidar las barras diagonales / al final de los nombres de directorio en rsync
  • --dry-run - simular sólo, no actualizar/transferir archivos
  • -r - recurrir a directorios
  • -v - detallado (pero no relacionado con la información de cambios de archivos)
  • --cvs-exclude - ignorar .svn archivos
  • -i - "--detallar-cambios:generar un resumen de cambios para todas las actualizaciones"

He aquí un breve extracto de man rsync que explica la información mostrada por -i (por ejemplo, el >f.st...... cadenas arriba):

The  "%i"  escape  has a cryptic output that is 11 letters long.
The general format is like the string YXcstpoguax,  where  Y  is
replaced  by the type of update being done, X is replaced by the
file-type, and the other letters represent attributes  that  may
be output if they are being modified.

The update types that replace the Y are as follows:

o      A  < means that a file is being transferred to the remote
       host (sent).

o      A > means that a file is being transferred to  the  local
       host (received).

o      A  c  means that a local change/creation is occurring for
       the item (such as the creation  of  a  directory  or  the
       changing of a symlink, etc.).

...
The file-types that replace the X are: f for a file, a d  for  a
directory,  an  L for a symlink, a D for a device, and a S for a
special file (e.g. named sockets and fifos).

The other letters in the string above  are  the  actual  letters
that  will be output if the associated attribute for the item is
being updated or a "." for no change.  Three exceptions to  this
are:  (1)  a newly created item replaces each letter with a "+",
(2) an identical item replaces the dots with spaces, and (3)  an
....

Un poco críptico, de hecho, pero al menos muestra una comparación básica de directorios ssh.¡Salud!

La respuesta clásica (System V Unix) sería dircmp dir1 dir2, que era un script de shell que enumeraría los archivos encontrados en dir1 pero no en dir2 o en dir2 pero no en dir1 al inicio (primera página de salida, de la pr comando, por lo tanto paginado con encabezados), seguido de una comparación de cada archivo común con un análisis (el mismo directorio, diferente, fueron los resultados más comunes).

Esto parece estar en proceso de desaparecer; tengo una reimplementación independiente disponible si la necesita.No es una ciencia exacta (cmp es tu amigo).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top