Impede que o diff verifique a nova linha no final do arquivo

19

Eu tenho duas grandes árvores, que quero comparar. Alguns dos arquivos na árvore diferem apenas porque um tem nova linha no final e o outro arquivo não possui essa nova linha. Eu quero ignorar esse fato. Eu tentei chamar diff assim:

diff --ignore-all-space -r <dir1> <dir2>

E isso está funcionando. Meu problema é que ele também ignora outras diferenças (relacionadas ao espaço), que podem ser importantes.

Em resumo: eu apenas quero ignorar a nova linha no EOF. Isso é possível com diff ?

    
por dangonfast 10.02.2012 / 09:37

6 respostas

15

Você basicamente precisa comparar dois arquivos, ignorando condicionalmente o byte final. Não existe uma opção 'diff' para fazer isso - mas há várias maneiras de fazer isso (por exemplo, hex diff também é lembrado).

Para usar 'diff', você basicamente tem que modificar os arquivos que estão faltando a nova linha no final de um arquivo e, em seguida, comparar. Você poderia criar um diretório temporário com os arquivos modificados ou, com um pouco de script, poderia ser feito na memória. (Quanto ao que é preferido depende da preferência, tamanho do arquivo, número de arquivos ...)

Por exemplo, o seguinte irá modificar o conteúdo de um arquivo (use sed -i para modificar no local, isso apenas imprime para stdout) para adicionar uma nova linha se estiver faltando (ou deixar o arquivo inalterado se já houver uma nova linha ):

sed -e '$a\'  file1.txt

E apenas para rever a sintaxe 'diff' (retornar true significa que eles são iguais, false 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 se apenas o espaço em branco é diferente:

$ diff --ignore-all-space  a/file1.txt   b/file1.txt \
     && echo '** are same' || echo '** are different'
** are same

No bash, podemos usar 'sed' para manipular o conteúdo do arquivo conforme ele é passado para 'diff' (arquivos originais deixados inalterados):

$ diff <(sed -e '$a\' a/file1.txt) <(sed -e '$a\' b/file1.txt) \
     && echo '** are same' || echo '** are different'
** are same

Agora, tudo o que você precisa fazer é emular diff -r para comparar diretórios recursivamente. Se comparar os diretórios a e b , todos os arquivos em a (por exemplo, a/dir1/dir2/file.txt ) receberão o caminho para o arquivo em b (por exemplo, b/dir1/dir2/file.txt ) e compararão:

$ for f in $( find a -type f  )
> do
>    diff <(sed -e '$a\' $f) <(sed -e '$a\' b/${f#*/})
> done

Uma versão ligeiramente mais detalhada:

$ 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
    
por 03.08.2012 / 21:49
0

Canalize a saída do comando diff para um comando grep que abandone a mensagem que você não deseja ver.

    
por 10.02.2012 / 11:08
0

Pense também em uma abordagem diferente, que funcionará para arquivos maiores (e ainda não copiará ou modificará os arquivos originais). Você ainda teria que emular o caminho de diretório recursivo (e há várias maneiras de fazer isso), mas este exemplo não usa 'sed', mas apenas compara dois arquivos, excluindo o último byte, usando cmp por exemplo,

$ cmp  a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
cmp: EOF on b/file1.txt
** are different

$ du -b a/file1.txt  b/file1.txt 
13  a/file1.txt
12  b/file1.txt

$ cmp  -n 12 a/file1.txt  b/file1.txt  && echo '** are same' || echo '** are different'
** are same

Ainda execute o loop sobre todos os arquivos no diretório e, para dois arquivos, um / file.txt eb / file.txt, calcule o tamanho de arquivo maior e subtraia um, em seguida, faça um diff binário ( cmp ) usando este número de bytes (também no bash):

(( bytes = $(du -b a/file.txt  b/file.txt  | sort -nr | head -1  | cut -f1) - 1 ))
cmp -n $bytes a/file.txt b/file.txt

Fazer um loop pelos arquivos seria o mesmo que na outra resposta usando sed e diff .

    
por 03.08.2012 / 22:08
0

A resposta é simples.
A mensagem sobre a nova linha ausente não está no fluxo de saída de diff , mas no fluxo de erros. Então, dobre isso para o nirvana e você está pronto para o bem

diff -rqEeB fileA fileB 2> /dev/null
    
por 20.05.2015 / 16:14
0

Resolvi o problema adicionando uma nova linha a cada um dos arquivos e ignorando linhas em branco no diff (opção -B ). Essas soluções podem não ser adequadas ao seu caso de uso, mas podem ajudar outras pessoas:

echo >> $FILE1 
echo >> $FILE2
diff -B $FILE1 FILE2 
    
por 12.06.2017 / 09:36
-1

Existe um sinalizador no diff commnad: --strip-trailing-cr que faz exatamente o que você pediu

    
por 09.10.2017 / 10:05

Tags