¿Cómo puedo hacer que 'diff -X' ignore rutas específicas y no nombres de archivos?

29

Obra: diff -r -X <ignore-list> <src-dir> <dest-dir>

no parece hacer diffignorar entradas en <ignore-list>si son de la forma <dir>/<file>.

<fileSin embargo, las entradas del formulario > se consideran. Este es un problema ya que podría tener varios archivos nombrados <file>en diferentes subdirectorios, algunos de los cuales no quiero ignorar.

Tampoco parece haber mucha información sobre la sintaxis del patrón en la página de manual diff. Por lo que puedo decir, es solo el nombre base de un archivo considerado por diff (consulte http://forums.gentoo.org/viewtopic-t-889788-start-0.html si está interesado).

Ceniza
fuente
diffla --excludeopción del hombre es una mierda ...
Elouan Keryell-Even

Respuestas:

30

Listado de directorios debería funcionar; por ejemplo, esto es lo que he usado en un script (suponiendo que gnu diff),

diff -r \
   --exclude="*~" \
   --exclude=".svn" \
   --exclude=".git" \
   --exclude="*.zip*" \
   --exclude="*.gz" \
   --exclude="*.tar" \
   ...etc

... que ignora el contenido .svny los .gitdirectorios, pero también los archivos individuales llamados *.zip/ *.gz/ etc.

Editar: para filtrar las rutas del formulario dir_a/file1pero aún los diffarchivos con el mismo nombre base, como dir_b/file1o dir_a/b/file1, entonces diffse tendría que generar una lista de archivos (por ejemplo, usando find) y el archivo para comparar derivado de estas rutas; por ejemplo, dado

$ find ONE TWO -type f -print 
ONE/a/1.txt
ONE/a/2.txt
ONE/a/b/2.txt
TWO/a/1.txt
TWO/a/2.txt
TWO/a/b/2.txt

genera la lista de archivos para comparar, excluyendo, por ejemplo, */a/2.txtpero aún comparando otros archivos nombrados 2.txt. Simplemente "encuentre" todos los archivos excepto ONE/a/2.txt(una expresión regular también se puede usar aquí, como .*/a/2.txt)

$ find ONE -type f \( ! -regex 'ONE/a/2.txt' \) \
    -exec bash -c 'diff -q "${1}" "${2/ONE/TWO}"' - {} {} \;  

que en efecto ignora ONE/a/2.txt(y TWO/a/2.txt), pero aún compara los otros archivos llamados 2.txt:

diff -q ONE/a/1.txt TWO/a/1.txt
diff -q ONE/a/b/2.txt TWO/a/b/2.txt

Editar: O, más divertido con find(diversión adicional dejada como un ejercicio para el lector), seleccione los archivos o directorios para excluir y luego difftodo lo demás:

$ find ONE \( -regex 'ONE/a/2.txt' -o -name b  -prune \)  \
    -o -type f -exec bash -c 'echo diff -q "${1}" "${2/ONE/TWO}"' - {} {} \

El ejemplo anterior excluye el archivo específico "{top} /a/2.txt", cualquier directorio llamado "b", y todo lo demás está diferido. (En lugar de " -name b" también podría usar " -regex '.*/b'" - nota, sin seguimiento "/".)

Miguel
fuente
2
Gracias pero creo que te estás perdiendo el punto. El único soporte que parece existir es cuando usa un 'nombre base'. Ese podría ser el nombre de un directorio o un archivo. En cualquier caso, diff ignora lo que has pedido. El problema surge cuando usas rutas. Por ejemplo, no puedo hacer que diff ignore / an / absolute / path / to / a / file o ./a/relative/path/to/a/file.
Ash
2
diff --exclude = "/ this / especifico / file / that / im / explicitly / pleading / you / to / ignore". No va a funcionar
Ash
3
correcto, los excludepatrones se comparan con el nombre base de los archivos (según gnu.org/software/diffutils/manual/html_node/… ); los caminos no funcionarán (como en foo/bar.txt). Para hacer eso, es probable que deba ejecutar findpara generar la lista de nombres de archivo y derivar la ruta del archivo para comparar.
michael
respuesta actualizada para incluir ejemplo exclusión de rutas de archivo de la diff, en lugar de usarbasename
Michael
Bien, veo lo que estás proponiendo, pero parece que hay un problema. Necesito considerar directorios también, no solo archivos (es decir, tipo f). Ahora, aunque todavía puede eliminar ciertos archivos usando regexp con find, si la entrada diffcontiene un directorio, pasará y comparará los archivos dentro de ese directorio y es posible que deba ignorar algunos de estos archivos ... volver a la casilla 1.
Ash
1

Para excluir el directorio directory/sub-directory, yo uso

diff -r <src-dir> <dest-dir> | grep -v directory/sub-directory

Sin embargo, aunque debería funcionar para una sola exclusión, no debería ser posible para una larga lista de ignorados como lo ha hecho.

Elouan Keryell-Even
fuente
-2
$ diff -rq foo.orig foo | grep -vP 'ignore1/|exclude2/' | awk '{print $2}' | cut -d'/' -f2- | xargs -I{} diff -u foo.orig/{} foo/{}
vern
fuente
1
Si bien esto puede responder la pregunta, sería una mejor respuesta si pudiera proporcionar alguna explicación de por qué lo hace.
DavidPostill