Encontrar Diferenças - Jogo de encontrar diferenças para crianças Transporte atividade ...
Jogo de encontrar diferenças para crianças Transporte atividade ...

Como comparar arquivos e achar o que mudou

A coisa mais simples do mundo é abrir dois arquivos e ver o que tem diferente entre eles. Mas na prática, quando você lida com centenas de arquivos ou structures de dados grandes, isso vira um pesadelo. Eu já perdi horas procurando uma linha que mudou em um config de mil linhas, só porque alguém alterou um espaço ou adicionou um ponto e vírgula no lugar errado. Vou te mostrar como fazer isso de verdade, sem enrolação.

Encontrar diferenças com diff clássico

O comando diff existe desde os anos 70 e continua sendo a ferramenta mais confiável pra isso. A sintaxe básica é:

diff arquivo1.txt arquivo2.txt

O resultado mostra linhas adicionadas (com >), removidas (com <) e modificadas. Parece simples, mas tem um problema: quando os arquivos são grandes, a saída é impossível de ler. Eu sempre uso a flag -u pra unificado, que mostra contexto ao redor das mudanças:

diff -u arquivo1.txt arquivo2.txt

Isso gera algo como:

--- arquivo1.txt
+++ arquivo2.txt
@@ -10,7 +10,7 @@
 linha que não mudou
 linha que não mudou
-valor_antigo
+valor_novo
 linha que não mudou

O @@ mostra o range de linhas afetadas. O - é do arquivo original, + é do novo. Se você quer só saber se tem diferença sem ver o quê, usa diff -q.

Comprensar com dircmp

Quando o problema é diretórios inteiros, não arquivos únicos. O comando diff sozinho não resolve. Você precisa recursivo:

diff -r dir1/ dir2/

O -r faz a comparação recursiva. Mas aqui tem uma pegadinha que ninguém conta: o diff mostra arquivos que existem em um diretório mas não no outro. Isso significa que se você criar um arquivo novo no dir2, ele aparece como "adicionado", mas se deletar, aparece como "removido". O diff não diferencia bem isso visualmente. Uma solução melhor é usar comm pra listar arquivos únicos de cada lado:

comm -23 <(ls dir1/ | sort) <(ls dir2/ | sort)

Isso mostra só o que existe em dir1 mas não em dir2. O -23 esconde colunas 2 e 3, deixando só a primeira. Invertendo os argumentos, você vê o contrário.

Diferenças binárias

Arquivos binários (imagens, PDFs, executáveis) não dão certo com diff texto. O cmp é feito pra isso:

cmp arquivo1.bin arquivo2.bin

Se nãooutputar nada, os arquivos são idênticos. Se tiver diferença, mostra a primeira posição onde divergem. Isso é útil pra verificar checksums ou downloads corrompidos. Eu já passei por um problema em que um arquivo de configuração de 50MB parecia idêntico visualmente, mas o cmp mostrava diferença no byte 47.293. Descobriu que era um caractere de controle invisível, tipo um tab ou espaços extras no final da linha. Sem o cmp, eu nunca teria achado.

Ferramentas gráficas

Quando as diferenças são muitas, ferramentas visuais ajudam. O meld é bonito e fácil:

meld dir1/ dir2/

O kdif2 funciona no KDE. O p4diff é pro Perforce. Cada uma tem seu nicho. Uma limitação importante: ferramentas gráficas não escalam. Com 10 mil arquivos, a interface fica lenta e impraticável. Nesses casos, volta pro diff textual com filtro:

diff -rq dir1/ dir2/ | grep -v "Arquivos" | head -50

Isso mostra só as primeiras 50 diferenças, sem a mensagem padrão "Arquivos X e Y são diferentes". Você pode redirecionar pra um arquivo e processar depois.

👉 Clique no botão abaixo para saber mais sobre o assunto!

Git diff

Se você já usa git, o git diff é poderoso porque mostra diferenças contra commits anteriores, não só entre dois estados atuais:

git diff HEAD~1 HEAD

Isso compara o commit atual com o anterior. Útil pra code review ou pra entender o que mudou numa release. O flag --stat mostra resumo:

git diff --stat HEAD~1 HEAD

Output:

 src/main.py | 15 +++++++++------
 config.json |  3 ++-
 2 files changed, 11 insertions(+), 7 deletions(-)

Isso é informação prática que você precisa antes de entrar no diff textual. Se mudou 15 linhas num arquivo de 500, você já sabe onde focar.

Edge case: arquivos com encoding diferente

Aqui tem um problema que quebra muita gente. Dois arquivos podem ser visualmente idênticos mas terem encoding diferente (UTF-8 vs UTF-8 BOM vs Latin1). O diff mostra diferença em TODO o arquivo, porque cada byte muda. Eu tive isso com um arquivo YAML que parecia certo, mas o diff acusava 200 linhas diferentes. Descobri que um editor salvava com BOM (três bytes no início: EF BB BF) e o outro não. A solução foi converter pros dois pros mesmo encoding antes de comparar:

iconv -f UTF-8 -t UTF-8 arquivo_bom.txt > arquivo_normalizado.txt

O iconv remove o BOM implicitamente quando converte de UTF-8 pros UTF-8 (ele padroniza). Depois disso, o diff mostra só as diferenças reais de conteúdo.

When diff falha completamente

Tem casos em que nenhuma ferramenta de diff resolve. Arquivos gerados dinamicamente (logs, datasets com timestamps) têm diferenças artificiais que não importam. Nesses casos, você normaliza antes de comparar:

sed 's/2024-01-15T10:30:00/[TIMESTAMP]/g' log1.log log2.log | diff -

O sed substitui timestamps por um placeholder fixo, então o diff ignora essa variação natural. É um workaround manual, mas funciona. Outro caso é diferença de line endings (CRLF vs LF). Arquivos criados no Windows vs Linux parecem diferentes pra diff mas são idênticos semanticamente. O diff -w ignora whitespace, mas não resolve CRLF. Você precisa converter antes:

unix2dos arquivo.txt  ou dos2unix

Depois comparar. Eu já gastei 40 minutos troubleshootando diferenças que eram só line endings. A ferramenta não avisa, então você tem que suspeitar.

Alternativas modernas

Se diff textual não entrega o que você precisa, tem alternativas. O rsync com flag -n (dry-run) mostra o que seria sincronizado, funcionando como diff de diretórios com informação de permissões:

rsync -avn dir1/ dir2/

O -a preserva metadados, -v é verbose, -n é dry-run. A saída mostra arquivos que seriam copiados, com tamanho e data. Útil pra validar backups ou migrações. Para JSON especificamente, o jq normaliza a output antes de comparar:

jq -S . arquivo1.json > norm1.json
jq -S . arquivo2.json > norm2.json
diff norm1.json norm2.json

O -S ordena keys alfabeticamente. Dois JSON com mesmas informações mas keys em ordem diferente parecem idênticos pro jq e diferentes pro diff direto. Sempre normaliza JSON antes de comparar.

Resumo prático

Use diff -u pra arquivos únicos. diff -r pra diretórios. cmp pra binários. git diff --stat pra versionamento. Converta encoding e line endings antes. Normalize JSON com jq -S. Ignore timestamps com sed. E quando tudo mais falha, abre os dois lado a lado e lê — às vezes a diferença óbvia é uma vírgula que passou despercebida.