Comparando arquivos
LidoEsta aula explora as principais ferramentas de comparação de arquivos no Linux/Bash: diff, comm e cmp, além de uma visão geral sobre patch. Você aprenderá a identificar diferenças entre arquivos, comparar arquivos ordenados e aplicar alterações. A aula inclui exemplos práticos, boas práticas e exercícios com respostas.
Comparar arquivos é uma tarefa comum no dia a dia de quem trabalha com programação, configuração de sistemas ou manipulação de dados. O Linux oferece ferramentas poderosas para essa finalidade, cada uma com suas particularidades. Nesta aula, vamos explorar três utilitários essenciais: diff, comm e cmp, além de uma introdução ao patch, que é usado para aplicar diferenças. Ao final, você terá um repertório sólido para analisar e sincronizar arquivos de forma eficiente.
Entender as diferenças entre essas ferramentas é crucial: diff mostra as diferenças linha a linha, comm compara arquivos já ordenados e cmp compara byte a byte. Cada uma tem seu uso específico, e saber escolher a ferramenta certa economiza tempo e evita erros.
diff
O comando diff é o mais conhecido para comparar arquivos de texto. Ele analisa dois arquivos e exibe as linhas que diferem entre eles, indicando como transformar o primeiro arquivo no segundo. A saída padrão é um conjunto de comandos que podem ser interpretados por humanos ou por outras ferramentas.
A sintaxe básica é diff [opções] arquivo1 arquivo2. Sem opções, a saída mostra as diferenças em um formato chamado "normal", que inclui instruções como a (adicionar), c (alterar) e d (deletar). Por exemplo, considere dois arquivos:
$ cat arquivo1.txt
linha1
linha2
linha3
$ cat arquivo2.txt
linha1
linha2 modificada
linha4
Executando diff arquivo1.txt arquivo2.txt, obtemos:
2,3c2,3
< linha2
< linha3
---
> linha2 modificada
> linha4
Isso indica que as linhas 2 e 3 do primeiro arquivo foram alteradas para as linhas 2 e 3 do segundo. O < representa o primeiro arquivo e o > o segundo.
O diff oferece várias opções úteis. A opção -u gera uma saída unificada, que é mais compacta e amplamente usada em sistemas de controle de versão. A opção -c gera uma saída com contexto, mostrando linhas ao redor das diferenças. Já a opção -i ignora diferenças de maiúsculas/minúsculas, e -w ignora espaços em branco.
$ diff -u arquivo1.txt arquivo2.txt
--- arquivo1.txt
+++ arquivo2.txt
@@ -1,4 +1,4 @@
linha1
-linha2
-linha3
+linha2 modificada
+linha4
O diff também pode ser usado recursivamente com a opção -r para comparar diretórios inteiros. Isso é muito útil para verificar mudanças em projetos de software.
Outra ferramenta relacionada é o diff3, que compara três arquivos e é útil para mesclar alterações, mas não será abordado em detalhes aqui.
comm
O comando comm compara dois arquivos que devem estar ordenados (lexicograficamente). Ele produz três colunas na saída: a primeira coluna contém linhas exclusivas do primeiro arquivo, a segunda coluna linhas exclusivas do segundo, e a terceira coluna linhas comuns aos dois. Por padrão, todas as colunas são exibidas, mas é possível suprimir colunas com as opções -1, -2 e -3.
Por exemplo, considere os arquivos:
$ cat lista1.txt
banana
laranja
maçã
$ cat lista2.txt
banana
pera
uva
Como estão ordenados (em ordem alfabética, com acentos), podemos executar:
$ comm lista1.txt lista2.txt
banana
laranja
maçã
pera
uva
A saída mostra que "banana" está nas duas listas (na terceira coluna, indicada por dois tabs), "laranja" e "maçã" são exclusivos do primeiro arquivo (primeira coluna, um tab), e "pera" e "uva" são exclusivos do segundo (segunda coluna).
Para obter apenas as linhas comuns, use comm -12 arquivo1 arquivo2. Para linhas exclusivas do primeiro, comm -23; para exclusivas do segundo, comm -13.
$ comm -12 lista1.txt lista2.txt
banana
O comm é particularmente útil quando você já tem arquivos ordenados, por exemplo, gerados por sort. Se os arquivos não estiverem ordenados, o resultado pode ser imprevisível, então é recomendável ordená-los antes.
cmp
Enquanto diff e comm trabalham com linhas de texto, o cmp compara arquivos byte a byte. Ele é útil para verificar se dois arquivos são idênticos, independentemente do tipo (binário ou texto). A sintaxe é cmp [opções] arquivo1 arquivo2.
Por padrão, o cmp não produz saída se os arquivos forem idênticos, e retorna o código de saída 0. Se forem diferentes, ele exibe a primeira posição em que diferem e retorna o código 1. Se ocorrer um erro, retorna 2.
$ cmp arquivo1.txt arquivo2.txt
arquivo1.txt arquivo2.txt diferem: byte 9, linha 2
$ echo $?
1
A opção -l (ou --verbose) exibe todas as diferenças, mostrando a posição e o valor de cada byte em octal. A opção -s (ou --silent) suprime toda a saída, apenas retornando o código de saída, o que é útil em scripts.
$ cmp -s arquivo1.txt arquivo2.txt; echo $?
1
O cmp é eficiente para verificar se dois binários são idênticos, como em testes de integridade. No entanto, para textos, o diff fornece informações mais detalhadas.
patch (visão geral)
O comando patch é usado para aplicar um arquivo de diferenças (gerado pelo diff) a um ou mais arquivos originais, transformando-os na versão modificada. É amplamente usado para distribuir alterações em projetos de software, como em listas de discussão ou correções de segurança.
O fluxo típico é: gerar um arquivo de diferenças com diff (normalmente no formato unificado) e depois usar patch para aplicá-lo. Por exemplo:
$ diff -u arquivo_original.txt arquivo_modificado.txt > mudancas.patch
$ patch arquivo_original.txt < mudancas.patch
patching file arquivo_original.txt
O patch também pode ser usado com a opção -p para controlar quantos componentes de diretório devem ser ignorados ao aplicar o patch, especialmente quando os caminhos nos cabeçalhos do diff incluem diretórios.
Para reverter um patch, use a opção -R. Isso restaura o arquivo ao estado original.
$ patch -R arquivo_original.txt < mudancas.patch
É importante verificar se o patch foi aplicado corretamente. O comando patch tenta aplicar o patch mesmo se as linhas de contexto não coincidirem exatamente, usando heurísticas, mas é recomendável fazer backup dos arquivos antes de aplicar.
Boas práticas e observações finais
Ao trabalhar com comparação de arquivos, algumas boas práticas podem evitar dor de cabeça:
- Use
diff -upara gerar patches mais legíveis e que podem ser aplicados compatch. - Sempre verifique o código de saída dos comandos em scripts, especialmente com
cmp -sediff -q(que apenas informa se os arquivos diferem). - Para arquivos grandes, o
cmpé mais rápido que odiffpara verificação de igualdade, pois não processa linhas. - Quando usar
comm, garanta que os arquivos estejam ordenados, por exemplo, usandosort -upara remover duplicatas. - Em projetos com controle de versão (git, SVN), as ferramentas de diff integradas são mais poderosas, mas conhecer os comandos básicos é fundamental para depuração e automação.
Dominar essas ferramentas aumenta sua produtividade no terminal e é essencial para tarefas como revisão de código, sincronização de arquivos e análise de logs.
Referências
- diff(1) - Linux manual page
- comm(1) - Linux manual page
- cmp(1) - Linux manual page
- patch(1) - Linux manual page
- GNU Diffutils Manual
- Comparing Files - GNU Diffutils
Exercícios
Crie dois arquivos de texto com algumas linhas diferentes e use
diffpara exibir as diferenças no formato unificado. Explique o significado de cada parte da saída.✓ Resposta: O formato unificado começa com cabeçalhos indicando os arquivos e as linhas afetadas. Por exemplo:
O trecho--- arquivo1.txt +++ arquivo2.txt @@ -1,4 +1,4 @@ linha1 -linha2 -linha3 +linha2 modificada +linha4@@ -1,4 +1,4 @@indica que as linhas 1 a 4 do arquivo original correspondem às linhas 1 a 4 do novo. Linhas precedidas por-são removidas, e por+são adicionadas. Linhas sem prefixo são contexto.- Dado dois arquivos ordenados, use
commpara listar apenas as linhas que estão no primeiro arquivo, mas não no segundo. Mostre o comando e a saída.✓ Resposta: Usecomm -23 arquivo1 arquivo2. Por exemplo, searquivo1contéma b cearquivo2contéma c, a saída seráb, pois está apenas no primeiro. - Escreva um script Bash que verifique se dois arquivos são idênticos usando
cmp -se imprima uma mensagem adequada. Inclua tratamento de erro caso os arquivos não existam.✓ Resposta:#!/bin/bash if [[ $# -ne 2 ]]; then echo "Uso: $0 arquivo1 arquivo2" exit 1 fi if [[ ! -f "$1" || ! -f "$2" ]]; then echo "Erro: um dos arquivos não existe." exit 1 fi if cmp -s "$1" "$2"; then echo "Os arquivos são idênticos." else echo "Os arquivos são diferentes." fi - Gere um patch a partir de dois arquivos usando
diff -ue aplique-o a um terceiro arquivo (que deve ser idêntico ao original). Verifique se a aplicação foi bem-sucedida.✓ Resposta:$ diff -u original.txt modificado.txt > mudancas.patch $ cp original.txt copia.txt $ patch copia.txt < mudancas.patch patching file copia.txt $ diff -q copia.txt modificado.txt && echo "Patch aplicado com sucesso!" - Explique a diferença entre
diff,commecmpe dê um exemplo de uso para cada um.✓ Resposta:diffmostra diferenças linha a linha em arquivos de texto, útil para ver alterações.commcompara arquivos ordenados e mostra linhas exclusivas/comuns em colunas.cmpcompara byte a byte, ideal para binários. Exemplos:diff -u old new,comm -12 sorted1 sorted2,cmp -s file1 file2.