scripts script resueltos programas pasar parametros operaciones manejo ejercicios ejemplos cadenas aritmeticas bash shell diff

bash - programas - scripts linux ejercicios resueltos



Cómo comparar archivos con los mismos nombres en dos directorios diferentes utilizando un script de shell (6)

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

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

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


El comando diff tiene una opción -r para comparar recursivamente los directorios:

diff -r /develop /main


El diff que tengo disponible permite las diferencias recursivas:

diff -r main develop

Pero con un script de shell:

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


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 dir2 o en dir2 pero no dir1 al inicio (primera página de salida, desde el comando pr , así paginado con encabezados), seguido por una comparación de cada archivo común con un análisis (el mismo, diferente, directorio fueron los resultados más comunes).

Esto parece estar en proceso de desaparición. Tengo una reimplementación independiente disponible si lo necesita. No es ciencia espacial ( cmp es tu amigo).


[Leí en algún lado que responder tus propias preguntas está bien, así que aquí va :)]

Intenté 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 ones] 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 guión mío (algo desordenado), dircompare.sh , que:

  • ordenar los archivos y directorios en matrices, según el directorio en el que se encuentren (o ambos), en dos pases recursivos
  • Los archivos que ocurren en ambos directorios, se ordenan de nuevo en dos matrices, dependiendo de si diff -q determina si difieren o no
  • para aquellos archivos que las reclamaciones de diff son iguales, muestre y compare las marcas de tiempo

Espero que se pueda encontrar útil. ¡Saludos!

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

EDITAR: ... excepto que parece bloquear mi servidor para un directorio ssh remoto (que traté de usar sobre ~/.gvfs ) ... Así que esto ya no es bash , pero una alternativa que supongo es usar rsync , aquí hay una 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 debe olvidar barras inclinadas / al final de los nombres de directorio en rsync
  • --dry-run - simular solamente, no actualizar / transferir archivos
  • -r - recurse en directorios
  • -v - verboso (pero no relacionado con la información de cambios de archivo)
  • --cvs-exclude - ignorar archivos .svn
  • -i - "--itemize-changes: genera un resumen de cambios para todas las actualizaciones"

Aquí hay un breve extracto de man rsync que explica la información mostrada por -i (por ejemplo, las >f.st...... anteriores):

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 a través de ssh . ¡Aclamaciones!


diff -rqu /develop /main

Solo le dará un resumen de los cambios de esa manera :)

Si quieres ver solo archivos nuevos / faltantes

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

Si quieres que estén al descubierto:

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