¿Cómo diferencia un directorio solo para archivos de un tipo específico?

88

Tengo una pregunta sobre el comando diff si quiero un diff de directorio recursivo pero solo para un tipo de archivo específico, ¿cómo hacerlo?

Intenté usar la opción de exclusión, pero solo puedo usar un patrón:

$ diff /destination/dir/1 /destination/dir/2 -r -x *.xml

con el comando sólo puedo excluir tipo de archivo XML, a pesar de que hay archivos en la carpeta de tipo de imagen ( png, gif, jpg), txt, php, etc.

cómo diferenciar sólo ciertos tipos de archivos.

de_3
fuente
1
stackoverflow.com/q/10131908/2707864
sancho.s ReinstateMonicaCellio
Entonces, ¿está intentando diferenciar archivos de un tipo específico o excluir esos archivos de diferencias? La pregunta no se correlaciona con la descripción ..
def

Respuestas:

97

Puede especificar -xmás de una vez.

diff -x '*.foo' -x '*.bar' -x '*.baz' /destination/dir/1 /destination/dir/2

Desde la sección de comparación de directorios de info diff(en mi sistema, tengo que hacer info -f /usr/share/info/diff.info.gz):

Para ignorar algunos archivos al comparar directorios, use la opción '-x PATTERN' o '--exclude = PATTERN'. Esta opción ignora cualquier archivo o subdirectorio cuyos nombres base coincidan con el patrón de shell PATTERN. A diferencia del shell, un punto al comienzo de la base de un nombre de archivo coincide con un comodín al comienzo de un patrón. Debe encerrar PATTERN entre comillas para que el shell no lo expanda. Por ejemplo, la opción -x '*. [Ao]' ignora cualquier archivo cuyo nombre termine con '.a' o '.o'.

Esta opción se acumula si la especifica más de una vez. Por ejemplo, el uso de las opciones -x 'RCS' -x '*, v' ignora cualquier archivo o subdirectorio cuyo nombre base sea 'RCS' o termine con ', v'.

Pausado hasta nuevo aviso.
fuente
El mío (ubuntu 10.04) no tiene estas líneas. También lo intenté y no funcionó. Supongo que esta es una nueva versión.
alumno
22

Tomado de (una versión de) la página de manual:

-x PAT  --exclude=PAT
  Exclude files that match PAT.

-X FILE    --exclude-from=FILE
  Exclude files that match any pattern in FILE.

Por lo tanto, parece que -xsolo acepta un patrón cuando informa, pero si coloca todos los patrones que desea excluir en un archivo (presumiblemente uno por línea), podría usar la segunda bandera de la siguiente manera:

$ diff /destination/dir/1 /destination/dir/2 -r -X exclude.pats

donde exclude.pats es:

*.jpg
*.JPG
*.xml
*.XML
*.png
*.gif
jamesbtate
fuente
4
Puede encontrar todas las extensiones de archivo dentro de su carpeta excepto la extensión <my-ext> con la siguiente línea de comando:find . -type f -not -name '*.<my-ext>' | xargs -I% basename '%' | awk -F . 'NF > 1 { print "*." $NF}; NF == 1 { print $NF }' | sort | uniq > exclude.pats
John
Ojalá hubiera notado el comentario de John antes, pero en macOs / bash encontré una solución similar para producir el archivo de exclusión con varios patrones para mantener: find . -not -name "*.c" -and -not -name "*.h" -and -type f -print0 | xargs -0 basename | grep -E '.*\..+' | sed 's/\./\//g' | xargs basename | xargs printf '*.%s\n' | sort | uniq > X-FILEquiero creer que eso ayuda, tal vez también en Linux. (En este ejemplo, un sencillo -name "*.[ch]"está bien, pero no es muy ilustrativo)
eruve
16

También puede usar find con -exec para llamar a diff:

cd /destination/dir/1
find . -name *.xml -exec diff {} /destination/dir/2/{} \;
Alex Harui
fuente
7

La falta de un complemento --incluye ...

Podemos hacer una solución alternativa, un archivo de exclusión con todos los archivos, pero lo que queremos incluir. Así que creamos file1con buscar todos los archivos que no tienen extensiones que queremos incluir, sedcapturamos el nombre del archivo y es solo:

diff --exclude-from=file1  PATH1/ PATH2/

Por ejemplo:

find  PATH1/ -type f | grep --text -vP "php$|html$" | sed 's/.*\///' | sort -u > file1 
diff PATH1/ PATH2/ -rq -X file1 
Sérgio
fuente
Super útil de una sola línea, gracias. En Mac OSX grep es ligeramente diferente y se convierte en find PATH1/ -type f | grep --text -v -e "php$" -e html$" | sed 's/.*\///' | sort -u > file1 diff PATH1/ PATH2/ -rq -X file1
mmacvicar
3

Usé el siguiente comando para encontrar la diferencia de todos los *.tmplarchivos entre DIR1y DIR2. En mi caso, esto no arrojó ningún falso positivo, pero puede serlo para usted, dependiendo del contenido de su DIRS.

diff --brief DIR1 DIR2 | grep tmpl

Mikhail Golubitsky
fuente
2

En caso de que le resulte conveniente, puede utilizar lo siguiente Makefile. Simplemente ejecute: "hacer parche"

#Makefile for patches

#Exlude following file endings
SUFFIX += o
SUFFIX += so
SUFFIX += exe
SUFFIX += pdf
SUFFIX += swp

#Exlude following folders
FOLDER += bin
FOLDER += lib
FOLDER += Image
FOLDER += models

OPTIONS = Naur

patch: 
    rm test.patch
    diff -$(OPTIONS) \
    $(foreach element, $(SUFFIX) , -x '*.$(element)') \
    $(foreach element, $(FOLDER) , -x '$(element)*') \
        org/ new/ > test.patch  

unpatch: 
    rm test.unpatch
    diff -$(OPTIONS) \
    $(foreach element, $(SUFFIX) , -x '*.$(element)') \
    $(foreach element, $(FOLDER) , -x '$(element)*') \
    new/ org/ > test.unpatch
Rafiz
fuente
1

La falta de un complemento complementario hace necesario el uso de patrones heurísticos tan complicados como

*.[A-Zb-ik-uw-z]*

para encontrar (principalmente) archivos java!

Jerry Miller
fuente
1

Si desea diferenciar las fuentes y mantenerlo simple:

diff -rqx "*.a" -x "*.o" -x "*.d" ./PATH1 ./PATH2 | grep "\.cpp " | grep "^Files"

Elimine el último grep si desea obtener los archivos que existen en solo una de las rutas.

Alex
fuente
0

Si bien no evita la existencia diffde otros archivos, si su objetivo es producir un archivo de parche, o similar, puede usar filterdiffel patchutilspaquete, por ejemplo, para parchear solo sus .pycambios:

diff -ruNp /path/1 /path/2 | filterdiff -i "*.py" | tee /path/to/file.patch
Cez
fuente