2011-07-15 13 views
50

Trabajando en un cuadro de Fedora Constantine. Estoy buscando diff dos directorios de forma recursiva para comprobar los cambios de origen. Debido a la configuración del proyecto (¡antes de mi propio compromiso con dicho proyecto! suspiro), los directorios contienen fuentes y binarios, así como grandes conjuntos de datos binarios. Mientras que diferir eventualmente funciona en estos directorios, tomaría quizás veinte segundos si pudiera ignorar los archivos binarios.Difiere un directorio recursivamente, Ignorando todos los archivos binarios:

Por lo que tengo entendido, diff no tiene un modo 'ignorar archivo binario', pero tiene un argumento de ignorar que ignorará la expresión regular dentro de un archivo. No sé qué escribir allí para ignorar los archivos binarios, independientemente de la extensión.

Estoy usando el siguiente comando, pero no ignora los archivos binarios. ¿Alguien sabe cómo modificar este comando para hacer esto?

diff -rq dir1 directorio2

+2

Trate de usar 'cmp' en lugar de' diff', no pasará por alto los archivos binarios, pero debe ser más rápido –

+0

Gracias por el consejo. –

+1

eek. esta es la justificación del poster-niño para el control de la fuente. si no lo estás usando, deberías. si la decisión no está en tus manos, debes discutir apasionadamente. su problema desaparecería con una configuración de git adecuada ... – fearlesstost

Respuesta

31

Quizás use grep -I (que es equivalente a grep --binary-files=without-match) como un filtro para ordenar los archivos binarios.

dir1='folder-1' 
dir2='folder-2' 
IFS=$'\n' 
for file in $(grep -Ilsr -m 1 '.' "$dir1"); do 
    diff -q "$file" "${file/${dir1}/${dir2}}" 
done 
+0

Esto parece extremadamente prometedor. ¡Comprobaré esto y le diré cómo funciona/acepto como respuesta si funciona! –

+0

Esto funcionó mucho más rápido para mí. Gracias. –

+2

¿Alguien sabe el propósito de 'IFS = $ '\ n''? – Zubin

0

Bueno, como una especie de crudo de verificación, se podría ignorar los archivos que coinciden con/\ 0 /.

+1

El problema es que no parece que diff siquiera admita ignorar archivos en absoluto. –

+1

El indicador '-x' se puede usar para ignorar archivos. – xdhmoore

0

utilizar una combinación de find y el comando file. Esto requiere que investigue un poco sobre el resultado del comando file en su directorio; a continuación, supongo que los archivos que desea diferenciar se informan como ascii. O bien, use grep -v para filtrar los archivos binarios.

#!/bin/bash 

dir1=/path/to/first/folder 
dir2=/path/to/second/folder 

cd $dir1 
files=$(find . -type f -print | xargs file | grep ASCII | cut -d: -f1) 

for i in $files; 
do 
    echo diffing $i ---- $dir2/$i 
    diff -q $i $dir2/$i 
done 

Ya que probablemente conoce los nombres de los grandes binarios, colocarlos en un hash-array y sólo lo hace el diff cuando un archivo no está en el hash, algo como esto:

#!/bin/bash 

dir1=/path/to/first/directory 
dir2=/path/to/second/directory 

content_dir1=$(mktemp) 
content_dir2=$(mktemp) 

$(cd $dir1 && find . -type f -print > $content_dir1) 
$(cd $dir2 && find . -type f -print > $content_dir2) 

echo Files that only exist in one of the paths 
echo ----------------------------------------- 
diff $content_dir1 $content_dir2  

#Files 2 Ignore 
declare -A F2I 
F2I=([sqlite3]=1 [binfile2]=1) 

while read f; 
do 
    b=$(basename $f) 
    if ! [[ ${F2I[$b]} ]]; then 
     diff $dir1/$f $dir2/$f 
    fi 
done < $content_dir1 
50

tipo de trampas, pero esto es lo que solía:

diff -r dir1/ dir2/ | sed '/Binary\ files\ /d' >outputfile 

Esto se compara de forma recursiva a dir1 dir2, sed elimina las líneas de los ficheros binarios (comienza con "archivos binarios"), entonces es redirigido a la outputfile.

+4

+1 para hacer trampa;) – Nippey

+0

¡gracias! cómo también excluir todos los archivos xml? – Serg

+5

@Serg Puede excluir archivos usando el indicador '-x'. Pruebe 'diff -r -x '* .xml' dir1 dir2' También,' man diff' para más información. – xdhmoore

10

Llegué a esta (antigua) pregunta buscando algo similar (archivos de configuración en un servidor de producción heredado en comparación con la instalación de apache predeterminada). Siguiendo la sugerencia de @ fearlesstost en los comentarios, git es lo suficientemente ligero y rápido como para ser probablemente más sencillo que cualquiera de las sugerencias anteriores. Copie version1 a un nuevo directorio. A continuación, realice:

git init 
git add . 
git commit -m 'Version 1' 

Ahora elimine todos los archivos de la versión 1 de este directorio y copie la versión 2 en el directorio. Ahora hazlo:

git add . 
git commit -m 'Version 2' 
git show 

Esto te mostrará la versión de Git de todas las diferencias entre el primer compromiso y el segundo. Para archivos binarios solo dirá que difieren. Alternativamente, podría crear una rama para cada versión e intentar fusionarlas usando las herramientas de combinación de git.

+2

O simplemente 'git diff folder1 folder2' ... –

0

Si los nombres de los archivos binarios en su proyecto siguen un patrón específico (* .o, * .so, ...), como suelen hacer, puede poner esos patrones en un archivo y especificarlo usando -X (guión X).

contenido de mi "archivo de exclusión" * .o * .so * .git

diff -X exclude_file -r . other_tree > my_diff_file 
+0

Es -x NO -X. –

Cuestiones relacionadas