Domine o comando `diff`: Compare arquivos de texto no Linux/macOS

Precisa identificar as discrepâncias entre duas versões de um arquivo de texto? O comando `diff` é a ferramenta ideal para essa tarefa. Este guia prático demonstra como utilizar o `diff` em ambientes Linux e macOS de maneira simples e eficaz.

Explorando o Comando `diff`

O comando `diff` atua comparando dois arquivos e gerando uma lista detalhada das diferenças encontradas. Essencialmente, ele revela as modificações necessárias para transformar o primeiro arquivo no segundo. Compreender esse princípio facilita a interpretação da saída do `diff`. Projetado para identificar diferenças em códigos-fonte, o `diff` produz uma saída que pode ser interpretada por outros programas, como o comando `patch`. Neste tutorial, exploraremos as formas mais práticas e acessíveis de usar o `diff`.

Vamos analisar dois arquivos como exemplo. A ordem dos arquivos na linha de comando determina qual é considerado o “primeiro” e qual é o “segundo” pelo `diff`. No exemplo a seguir, `alpha1` é o primeiro e `alpha2` o segundo. Ambos contêm o alfabeto fonético, mas o `alpha2` foi editado, resultando em arquivos distintos.

Para comparar os arquivos, execute `diff`, seguido pelo nome do primeiro arquivo, um espaço e o nome do segundo arquivo, pressionando Enter:

diff alpha1 alpha2

Como decifrar essa saída? Não é tão complicado quanto parece. As diferenças são listadas sequencialmente em uma coluna, cada uma com sua própria etiqueta. Uma etiqueta típica inclui números separados por uma letra, como `4c4`. O primeiro número refere-se à linha em `alpha1` e o segundo à linha correspondente em `alpha2`. A letra indica:

`c`: A linha no primeiro arquivo precisa ser alterada para corresponder à linha no segundo arquivo.
`d`: A linha no primeiro arquivo precisa ser eliminada para corresponder ao segundo.
`a`: Conteúdo adicional precisa ser adicionado ao primeiro arquivo para igualá-lo ao segundo.

No nosso exemplo, `4c4` indica que a quarta linha de `alpha1` deve ser alterada para se igualar à quarta linha de `alpha2`. Esta é a primeira discrepância detectada.

Linhas que começam com `>` referem-se ao segundo arquivo, `alpha2`. A linha `> Dave` indica que “Dave” é o conteúdo da quarta linha em `alpha2`. Em resumo, para que a quarta linha de ambos os arquivos coincida, devemos substituir “Delta” por “Dave” em `alpha1`.

A próxima mudança, indicada por `12c12`, significa que a linha 12 em `alpha1` contém “Lima”, enquanto a linha 12 em `alpha2` contém “Linux”.

A terceira alteração, `21d20`, indica que a linha 21 precisa ser excluída do primeiro arquivo para que ambos correspondam a partir da linha 20.

A quarta diferença, rotulada como `26a26,28`, refere-se a três linhas extras adicionadas ao `alpha2`. O intervalo `26,28` indica as linhas 26 a 28. Portanto, devemos adicionar as linhas 26 a 28 de `alpha2` à linha 26 de `alpha1`, contendo as palavras “peculiar”, “estranho” e “charme”.

Comandos Concisos

Para verificar se dois arquivos são idênticos, utilize a opção `-s` (relatar arquivos idênticos):

diff -s alpha1 alpha3

A opção `-q` (breve) gera uma notificação concisa caso dois arquivos sejam diferentes:

diff -q alpha1 alpha2

Importante notar que, com dois arquivos idênticos, a opção `-q` não retorna qualquer saída.

Visualização Alternativa

A opção `-y` (lado a lado) oferece uma descrição das diferenças em um formato distinto. Usar a opção `-W` (largura) para limitar o número de colunas é frequentemente útil, evitando saídas mal formatadas. Abaixo, pedimos ao `diff` para exibir a saída lado a lado, limitando a largura a 70 colunas:

diff -y -W 70 alpha1 alpha2

O primeiro arquivo (`alpha1`) aparece à esquerda, e o segundo (`alpha2`) à direita. As linhas correspondentes são exibidas lado a lado. Caracteres indicadores ao lado das linhas em `alpha2` sinalizam alterações, exclusões ou adições:

`|`: Uma linha modificada no segundo arquivo.
`<`: Uma linha excluída do segundo arquivo.
`>`: Uma linha adicionada ao segundo arquivo que não existe no primeiro.

Para uma visão mais compacta das diferenças, utilize a opção `–suppress-common-lines`, que restringe a saída às linhas modificadas, adicionadas ou excluídas:

diff -y -W 70 --suppress-common-lines alpha1 alpha2

Adicionando Cor

A ferramenta `colordiff` adiciona cores à saída do `diff`, facilitando a identificação das diferenças:

Para instalar em sistemas baseados em Debian como o Ubuntu, use:

sudo apt-get install colordiff

Para outras distribuições, use o gerenciador de pacotes correspondente.

Utilize `colordiff` da mesma maneira que `diff`:

`colordiff` é, na verdade, um wrapper para `diff`. Portanto, todas as opções do `diff` funcionam com `colordiff`:

Contextualização

Para um equilíbrio entre mostrar todas as linhas e apenas as alteradas, podemos usar opções do `diff` que mostram contexto, ou seja, linhas antes e depois das diferenças, para entender o arquivo em torno dos trechos modificados. Há duas formas de fazer isso:

A primeira usa a opção `-c` (contexto copiado):

colordiff -c alpha1 alpha2

A saída inclui um cabeçalho com os nomes dos arquivos e suas datas de modificação. Asteriscos (*) indicam o primeiro arquivo, e travessões (-) o segundo. Esses símbolos são usados para identificar a qual arquivo cada linha pertence.

Uma linha com asteriscos e o número `1,7` indica que estamos vendo as linhas 1 a 7 de `alpha1`. A palavra “Delta” está sinalizada em vermelho com uma exclamação (!), indicando a alteração. Linhas inalteradas são mostradas antes e depois para fornecer contexto.

A linha com travessões e `1,7` indica as linhas 1 a 7 de `alpha2`, com “Dave” na linha 4 sinalizada como diferente.

colordiff -C 2 alpha1 alpha2

Três linhas de contexto antes e depois de cada alteração são mostradas por padrão. Você pode especificar quantas linhas deseja com a opção `-C` (contexto copiado) seguida do número desejado.

colordiff -u alpha1 alpha2

A segunda opção para exibir contexto é a opção `-u` (contexto unificado).

A saída também inclui um cabeçalho com nomes e datas de modificação. Travessões (-) indicam `alpha1` e sinais de adição (+) indicam `alpha2`. Linhas iniciadas com `@` marcam o início de cada diferença e as linhas correspondentes de cada arquivo.

O contexto de três linhas é exibido antes e depois da diferença. As linhas com alterações são mostradas uma sobre a outra, precedidas por traços para `alpha1` e sinais de mais para `alpha2`. O resultado é mais compacto do que a opção anterior.

colordiff -U 2 alpha1 alpha2

Similar à opção `-C`, você pode definir o número de linhas de contexto unificado usando a opção `-U` seguida do número desejado.

Ignorando Espaços e Maiúsculas/Minúsculas

colordiff -y -W 70 test4 test5

Vamos analisar outros dois arquivos: `test4` e `test5`, contendo nomes de super-heróis.

O `diff` não encontra diferenças em “Viúva Negra”, “Homem-Aranha” e “Thor”, mas aponta mudanças em “Capitão América”, “Ironman” e “The Hulk”.

As diferenças são: em `test5`, “Hulk” está escrito com um “h” minúsculo; “Capitão América” tem um espaço extra entre “Capitão” e “América”. Quanto a “Ironman”, não há diferenças visíveis. Nesses casos, geralmente o problema é algum caractere de espaço ou tabulação invisível ao final da linha.

Se esses detalhes não importam, você pode instruir o `diff` a ignorá-los:

`-i`: Ignora diferenças de maiúsculas e minúsculas.
`-Z`: Ignora espaços em branco à direita.
`-b`: Ignora variações na quantidade de espaços em branco.
`-w`: Ignora todas as diferenças de espaços em branco.

colordiff -i -y -W 70 test4 test5

Vamos rodar o `diff` novamente, mas agora ignorando as diferenças de maiúsculas e minúsculas.

colordiff -i -Z -y -W 70 test4 test5

As linhas “The Hulk” e “The hulk” agora são consideradas idênticas, e a diferença no “h” minúsculo é ignorada. Vamos instruir o `diff` a também ignorar espaços em branco à direita.

colordiff -i -w -y -W 70 test4 test5

Como esperado, a diferença em “Ironman” era o espaço em branco, que o diff agora ignora. Resta “Capitão América”. Vamos instruir o `diff` a ignorar maiúsculas/minúsculas e espaços em branco.

Ao instruir o `diff` a ignorar as diferenças que não são relevantes, ele nos informa que os arquivos são, para os nossos propósitos, idênticos. O comando `diff` possui muitas outras opções, a maioria relacionada à geração de saídas interpretáveis por máquina. Estas podem ser consultadas na página man do Linux.

As opções que exploramos acima permitem que você rastreie todas as diferenças entre as versões dos seus arquivos de texto, usando o terminal e com observação humana.