Linux / Comando cmp: comparar bytes, limitar trechos e interpretar o resultado
O comando cmp compara dois arquivos byte a byte e, por padrão, informa a primeira diferença ou que um arquivo termina antes do outro. No GNU cmp, o estado de saída 0 indica ausência de diferenças no intervalo comparado, 1 indica diferenças e 2 indica um problema; para apenas testar a igualdade, use -s e examine esse estado.
A prática usa Bash e utilitários GNU para criar dez arquivos pequenos em uma pasta exclusiva. Execute os blocos na ordem e no mesmo terminal. As opções seguem o manual do GNU cmp e a página de manual distribuída pelo Debian. Confira cmp --version, cmp --help e man cmp no sistema de destino antes de depender de opções específicas.
O que o cmp verifica?
A comparação considera os bytes, sem interpretar campos de um formato, converter codificações ou ignorar espaços. O comando não modifica as entradas. Para ler alterações de linhas em configurações ou código, diff -u costuma ser mais informativo. O cmp compara dois arquivos; não é uma ferramenta de comparação recursiva de diretórios.
Sintaxe básica
cmp [opções] -- ARQUIVO1 [ARQUIVO2 [PULAR1 [PULAR2]]]
ARQUIVO e PULAR são marcadores da sintaxe. Use -- antes dos caminhos e coloque caminhos entre aspas. Se o segundo arquivo for omitido, ou um arquivo for indicado como -, GNU cmp lê a entrada padrão e pode aguardar dados. Nos exemplos abaixo, os dois nomes são fornecidos explicitamente. Os operandos opcionais PULAR1 e PULAR2 indicam quantos bytes iniciais desconsiderar; a prática usa a opção -i para tornar esse propósito visível.
Uso básico do cmp
Preparar os arquivos e encontrar a primeira diferença
Os arquivos image-a.bin e image-b.bin terão seis bytes: A, B, C, uma quebra de linha, um byte nulo e, por fim, Z ou Y. Portanto, a primeira diferença deve estar no byte 6, na linha 2. A numeração começa em 1 e conta bytes, não caracteres Unicode. A última comparação retorna 1 de propósito; pare se houver erro na preparação. Não é necessário imprimir esses arquivos binários diretamente no terminal.
cmp_demo=$(mktemp -d -p "$PWD" 'cmp-demo.XXXXXXXX') &&
printf '\101\102\103\012\000\132' > "$cmp_demo/image-a.bin" &&
printf '\101\102\103\012\000\131' > "$cmp_demo/image-b.bin" &&
cp -- "$cmp_demo/image-a.bin" "$cmp_demo/image-copy.bin" &&
printf '%s' 'A' > "$cmp_demo/first.bin" &&
printf '%s' 'B' > "$cmp_demo/second.bin" &&
printf '%s' 'HEADsameOLD' > "$cmp_demo/range-a.bin" &&
printf '%s' 'HEADsameNEW' > "$cmp_demo/range-b.bin" &&
printf '%s\n' 'AAAAconteudo' > "$cmp_demo/payload-a.bin" &&
printf '%s\n' 'BBBBconteudo' > "$cmp_demo/payload-b.bin" &&
printf '%s\n' 'CCconteudo' > "$cmp_demo/payload-short.bin" &&
cmp -- "$cmp_demo/image-a.bin" "$cmp_demo/image-b.bin"
Verificar igualdade sem relatório
O arquivo image-copy.bin é uma cópia de image-a.bin. A consulta abaixo deve ficar silenciosa e retornar 0. Confira $? imediatamente após a execução se estiver no terminal: outro comando substitui esse valor. O modo -s não distingue igualdade, diferença e erro pela aparência da tela; essa distinção depende do estado, como mostra o exemplo de script adiante.
cmp -s -- "$cmp_demo/image-a.bin" "$cmp_demo/image-copy.bin"
Limitar a comparação aos primeiros cinco bytes
Os primeiros cinco bytes dos arquivos image-a.bin e image-b.bin são iguais, por isso o bloco retorna 0. A divergência no sexto byte fica fora da análise. Trocar -n 5 por -n 6 faz a comparação retornar 1. O limite é um máximo: -n não exige que cada entrada tenha esse tamanho, e comparar dois arquivos iguais menores que o limite também pode retornar 0. Não use uma comparação parcial como prova de igualdade do arquivo inteiro.
cmp -n 5 -- "$cmp_demo/image-a.bin" "$cmp_demo/image-b.bin"
Ler a posição e a linha da primeira diferença
A preparação também cria first.bin contendo A e second.bin contendo B. O subshell entra na pasta da prática e fixa a localidade C somente para a comparação, para que o texto do diagnóstico seja previsível. O resultado abaixo corresponde ao GNU cmp; outras implementações e localidades podem usar palavras diferentes. No GNU cmp 3.12 com essa localidade, o rótulo char do relatório ainda representa uma posição de byte, não uma contagem de caracteres Unicode.
(
cd -- "$cmp_demo" || exit
LC_ALL=C cmp -- first.bin second.bin
)
Saída esperada para os dois arquivos de um byte:
first.bin second.bin differ: char 1, line 1
O byte 1 já difere, na linha 1, e o estado é 1. Isso é diferente de um erro de acesso. Se todos os bytes em comum forem iguais, mas uma entrada terminar antes, GNU cmp informa EOF, abreviação de fim de arquivo, em stderr e também retorna 1. Portanto, uma mensagem em stderr não significa, por si só, estado 2: examine o resultado numérico. Uma entrada inexistente, por exemplo, é um problema de comparação.
Principais opções
| Opção | Uso no GNU cmp |
|---|---|
-s, --silent |
Consultar o resultado pelo estado de saída, sem o relatório normal. |
-l, --verbose |
Listar posições em decimal e valores dos bytes diferentes em octal; uma entrada menor também pode gerar aviso de EOF. |
-b, --print-bytes |
Acrescentar uma representação dos bytes diferentes, com notação própria para controles e bytes não ASCII. |
-i N |
Ignorar os primeiros N bytes de cada entrada. |
-i N:M |
Ignorar N bytes da primeira entrada e M da segunda. |
-n N |
Comparar no máximo N bytes após os saltos, se houver. |
Na prática, cmp -l -- "$cmp_demo/image-a.bin" "$cmp_demo/image-b.bin" deve listar uma diferença: posição decimal 6, com valores octais 132 e 131, correspondentes a Z e Y. Os espaços de alinhamento podem variar. Não leia 132 e 131 como valores decimais. Para detalhes dos saltos e limites, consulte as opções oficiais do GNU cmp.
Exemplos práticos
Tratar igualdade, diferença e problema separadamente
O bloco deve imprimir Bytes diferentes. e terminar com estado 1. A comparação fica dentro de um if, o que permite capturar seu resultado mesmo em um script com set -e. A ramificação de erro usa stderr e preserva o estado, em vez de chamar todo resultado diferente de zero de arquivos diferentes. Para testar a igualdade, use image-copy.bin como segunda entrada; para observar um problema, use apenas um nome inexistente dentro da pasta de prática. Os parênteses mantêm a variável result e o exit dentro do subshell. O exit final devolve 1 quando há diferenças; um chamador com set -e ainda pode parar nesse ponto e deve decidir como tratar o resultado.
(
if cmp -s -- "$cmp_demo/image-a.bin" "$cmp_demo/image-b.bin"; then
result=0
else
result=$?
fi
case $result in
0) printf '%s\n' 'Bytes iguais.' ;;
1) printf '%s\n' 'Bytes diferentes.' ;;
*) printf 'Nao foi possivel comparar (estado %s).\n' "$result" >&2 ;;
esac
exit "$result"
)
Comparar um cabeçalho de tamanho conhecido
Os arquivos range-a.bin e range-b.bin começam por HEAD, seguido por sameOLD ou sameNEW. -n 4 compara somente HEAD e retorna 0; -n 8 ainda compara uma região igual, mas -n 9 alcança o primeiro byte diferente. Quatro bytes são o cabeçalho escolhido para este exercício, não um tamanho universal de imagens ou contêineres. Em um arquivo real, obtenha o deslocamento e o tamanho na especificação do formato e confira separadamente se a região esperada existe.
cmp -n 4 -- "$cmp_demo/range-a.bin" "$cmp_demo/range-b.bin"
Pular cabeçalhos e comparar o restante
payload-a.bin começa por AAAA e payload-b.bin por BBBB, seguidos pelo mesmo conteúdo e uma quebra de linha. O salto de quatro bytes ignora a diferença dos cabeçalhos e deve retornar 0. payload-short.bin começa por CC: compare-o com a primeira entrada usando cmp -i 4:2 -- "$cmp_demo/payload-a.bin" "$cmp_demo/payload-short.bin" para alinhar os conteúdos. Saltar além do fim pode deixar uma região vazia; dois restos vazios podem comparar iguais. Nenhum desses resultados valida os bytes ignorados.
cmp -i 4 -- "$cmp_demo/payload-a.bin" "$cmp_demo/payload-b.bin"
Comparar cmp e comandos relacionados
| Comando | Função principal | Quando usar |
|---|---|---|
cmp |
Comparar bytes e localizar a primeira diferença | Conferir arquivos acessíveis localmente ou regiões específicas |
diff |
Mostrar alterações de texto por linha | Revisar o conteúdo alterado com contexto |
sha256sum |
Calcular um resumo de cada arquivo | Comparar resumos obtidos em locais ou momentos diferentes |
comm |
Separar linhas comuns e exclusivas de entradas ordenadas | Comparar listas ordenadas sob o mesmo critério |
Cuidados importantes
Controlar o volume de saída e o intervalo
Em arquivos grandes com muitas diferenças, -l pode produzir uma linha por posição diferente entre os bytes comparados. Comece pelo modo padrão ou por -s e use -n quando uma região limitada for suficiente. O relatório de bytes não realinha inserções: acrescentar um byte no início pode deslocar muitas posições seguintes. Para texto, isso costuma ser mais claro em diff. Com saltos e limites, anote o intervalo realmente analisado antes de interpretar um resultado 0.
Usar o estado final e preservar as entradas
A ausência de texto não basta para concluir que as entradas são iguais, especialmente com -s. Separe 0, 1 e 2 e não dependa de analisar frases traduzidas do relatório. Evite redirecionar a saída para um dos arquivos de entrada: o shell pode truncá-lo antes da comparação. Arquivos que mudam durante a execução também limitam a conclusão; o cmp não cria uma captura atômica do par. A igualdade do conteúdo não certifica permissões, proprietário ou outros metadados.
Separar igualdade de bytes, validade e origem
Duas cópias idênticas ainda podem conter o mesmo arquivo inválido ou indesejado. O cmp não valida assinaturas, origem nem a estrutura de um formato. Um hash recebido pelo mesmo canal que um arquivo também não estabelece sozinho uma origem confiável. Em textos, codificações e finais de linha diferentes podem gerar bytes distintos mesmo quando a aparência é semelhante; use diff para examinar as alterações, sem confundir apresentação com igualdade exata.
Perguntas frequentes
A ausência de saída significa que os arquivos são iguais?
Só interprete o resultado após conferir o estado final. Com 0, não houve diferenças na região comparada; -s também pode deixar a tela vazia em outros resultados, e -n ou -i limitam a conclusão ao trecho escolhido.
Como mostrar todas as posições diferentes?
Use -l e leia a posição em decimal e os valores em octal. O relatório pode ser grande; um arquivo que termina antes do outro também pode gerar aviso de EOF. Isso não funciona como um alinhamento de linhas.
O cmp pode comparar arquivos de texto?
Sim. Ele compara os bytes sem normalizar a codificação ou o espaçamento. Para ver linhas removidas, adicionadas e contexto, use diff -u.
Qual é a diferença entre cmp e um checksum?
O cmp compara duas entradas acessíveis na execução. Um checksum é um resumo calculado separadamente e pode ser guardado ou transmitido. A comparação de resumos exige um valor de referência confiável quando a origem do arquivo importa.




