Básicamente, necesita comparar dos archivos, ignorando condicionalmente el byte final. No hay una opción 'diff' para hacer esto, pero hay varias formas de hacerlo (por ejemplo, hexadecimal diff también me viene a la mente).
Para usar 'diff', básicamente tiene que modificar los archivos a los que les falta la nueva línea al final de un archivo, y luego compararlos. Puede crear un directorio temporal con los archivos modificados, o con un poco de secuencia de comandos se puede hacer en la memoria. (En cuanto a cuál se prefiere depende de la preferencia, el tamaño del archivo, el número de archivos ...)
Por ejemplo, lo siguiente modificará el contenido de un archivo (se usa sed -i
para modificar en el lugar, esto solo se imprime en stdout) para agregar una nueva línea si falta una (o dejar el archivo sin cambios si ya hay una nueva línea):
sed -e '$a\' file1.txt
Y solo para revisar la sintaxis 'diff' (devolver verdadero significa que son iguales, falso significa diferente):
$ diff a/file1.txt b/file1.txt \
&& echo '** are same' || echo '** are different'
2c2
< eof
---
> eof
\ No newline at end of file
** are different
Verifique que solo los espacios en blanco sean diferentes:
$ diff --ignore-all-space a/file1.txt b/file1.txt \
&& echo '** are same' || echo '** are different'
** are same
En bash, podemos usar 'sed' para manipular el contenido del archivo a medida que se pasa a 'diff' (los archivos originales no se modifican):
$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
&& echo '** are same' || echo '** are different'
** are same
Ahora todo lo que tiene que hacer es emular diff -r
para comparar directorios de forma recursiva. Si compara directorios a
y b
, para todos los archivos en a
(p. Ej. a/dir1/dir2/file.txt
) , Deriva la ruta al archivo en b
(p. Ej. b/dir1/dir2/file.txt
) Y compara:
$ for f in $( find a -type f )
> do
> diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done
Una versión un poco más detallada:
$ for f in $( find a -type f )
> do
> f1=$f
> f2=b/${f#*/}
> echo "compare: $f1 $f2"
> diff <(sed -e '$a\' $f1) <(sed -e '$a\' $f2) \
> && echo '** are same' || echo '** are different'
> done && echo '** all are same' || echo '** all are different'
compare: a/file1.txt b/file1.txt
** are same
compare: a/file2.txt b/file2.txt
** are same
** all are same
sed -e '$a\'
hace exactamente? thxsed
, dada la siguiente-e
secuencia de comandos / expresión ( ), que coincide con el final del archivo ($
), y realizar la acción "agregar" (a \), pero en realidad no especifica ningún texto (nada después del `\`) que todavía va a agregar un EOF / nueva línea al final del archivo (solo si falta).a\
aún.Resolví el problema agregando una nueva línea a cada uno de los archivos e ignorando las líneas en blanco en la diferencia (opción
-B
). Estas soluciones pueden no ser adecuadas para su caso de uso, pero podrían ayudar a otros:fuente
Canalice la salida de
diff
ungrep
comando que suelte el mensaje que no desea ver.fuente
Solo pensé en un enfoque diferente, que funcionará para archivos más grandes (y aún así no copia ni modifica los archivos originales). Todavía tendría que emular el recorrido recursivo del directorio (y hay varias formas de hacerlo), pero este ejemplo no usa 'sed', sino que simplemente compara dos archivos, excluyendo el último byte, usando
cmp
, por ejemplo,Todavía repita todos los archivos en el directorio, y para dos archivos a / file.txt y b / file.txt, calcule el tamaño de archivo más grande y reste uno, luego haga un diff binario (
cmp
) usando este número de bytes (también en golpetazo):Recorrer los archivos sería lo mismo que en la otra respuesta usando
sed
ydiff
.fuente
La respuesta es simple.
El mensaje sobre la nueva línea que falta no está en la secuencia de salida de,
diff
sino en la secuencia de error. Así que dóblalo al nirvana y listofuente
Hay una bandera en diff commnad:
--strip-trailing-cr
que hace exactamente lo que pedistefuente
/r/n
como/n
y no tiene nada que ver con extra/n
justo antes de EOF.