Executando verificação de segurança...
7

Qual a diferença entre more, cat, less, hexdump, xxd, tac?

Content for testing purposes. Testing API for automatic content posting on Tabnews.

Ao inspecionar um arquivo texto utilizando o filtro more na linha de comando Linux, notei que o conteúdo exibido era de comprimento bem inferior ao tamanho listado para o arquivo (total de 166 bytes).

more
$ more sample.txt
3FBFF4D54AEA8CD5CB530D32D7F57A97

Nota-se claramente que o conteúdo exibido tem bem menos que 166 bytes como esperado.

Daí pensei usar o cat para ver se o conteúdo apareceria e, novamente, o conteúdo exibido não era coerente com o tamanho do arquivo.

cat
$ cat sample.txt
3FBFF4D54AEA8CD5CB530D32D7F57A97

Recorrí a uma ferramenta mais avançada, o hexdump para exibir o real conteúdo do arquivo e caracteres imprimíveis. Quem sabe o arquivo continha alguma sequência de zeros, por exemplo, por erro de tamanho registrado no inode do arquivo.

hexdump
$ hexdump -Cv sample.txt 
00000000  64 69 73 74 61 6e 63 65  0d 7a 65 72 6f 0d 63 72  |distance.zero.cr|
00000010  79 73 74 61 6c 0d 6e 6f  69 73 65 0d 70 6f 74 61  |ystal.noise.pota|
00000020  74 6f 0d 68 65 6c 6d 65  74 0d 63 6f 69 6c 0d 64  |to.helmet.coil.d|
00000030  67 69 61 6e 74 0d 61 64  64 0d 68 69 70 0d 73 74  |giant.add.hip.st|
00000040  69 6e 67 0d 66 61 6e 63  79 0d 30 35 30 39 3b 32  |ing.fancy.0509;2|
00000050  30 34 35 3b 30 34 32 36  3b 31 31 39 38 3b 31 33  |045;0426;1198;13|
00000060  35 30 3b 30 38 35 35 0d  30 33 36 32 3b 30 37 38  |50;0855.0362;078|
00000070  31 3b 30 30 32 35 3b 30  38 36 33 3b 31 37 31 31  |1;0025;0863;1711|
00000080  3b 30 36 36 33 0d 33 46  42 46 46 34 44 35 34 41  |;0663.3FBFF4D54A|
00000090  45 41 38 43 44 35 43 42  35 33 30 44 33 32 44 37  |EA8CD5CB530D32D7|
000000a0  46 35 37 41 39 37                                 |F57A97|
000000a6

Com isso, pude constatar que o arquivo contém várias palavras que não foram apresentadas na tela com os dois primeiros utilitários. Estão todas separadas com retorno de carro (caractere 0x0D). Na verdade, esse caractere não é um separador, mas um terminador de linha como se verá mais adiante com detalhes.

Notando essa surpresa "pregada" pelos utilitários cat e more, lembrei-me do less, afinal, less does more than more. Surpreendentemente os caracteres não imprimíveis bagunçam um pouco a exibição, mas apresentam mais detalhes que more e cat revelando parte do conteúdo oculto.

less
$ less sample.txt 
<várias linhas em branco>
distance^Mzero^Mcrystal^Mnoise^Mpotato^Mhelmet^Mcoil^Mdgiant^Madd^Mhip^Msting^Mfancy^M0509;2045;0426;1198;1350;0855^M0362;0781;0025;0863;1711;0663^M3FBFF4D54AEA8CD5CB530D32D7F57A97
sample.txt (END)

Terminadores de linha

Se chegou a leitura até aqui, vale lembrar-se que esse é um dos problemas que pode ser causado por arquivos texto criados em diferentes sistemas operacionais (entre Linux, Mac e Microsoft Windows). Cada um deles possui sua própria definição de caracteres terminadores de linha:

  • Linux (LF ou 0x0A)
  • Mac (CR ou 0x0D)
  • Windows (CRLF ou 0x0D0A)

Existem aplicações que realizam a compatiblização desses terminadores de linha:

  • dos2unix
  • mac2unix
  • unix2dos
  • unix2mac
A solução para toda essa surpresa poderia ser resolvida utilizando um destes utilitários...
$ mac2unix sample.txt
$ more sample.txt 
distance
zero
crystal
noise
potato
helmet
coil
dgiant
add
hip
sting
fancy
0509;2045;0426;1198;1350;0855
0362;0781;0025;0863;1711;0663
3FBFF4D54AEA8CD5CB530D32D7F57A97

Finalmente

O motivo de compatilhar essa surpresa foi para evidenciar que a inspeção de arquivos na linha de comando simplesmente com os utilitários cat e more citados pode causar uma falha nesta inspeção visual dependendo do sistema operacional.

  • Um bom uso desse artifício seria, por exemplo, esconder as linhas de comentários ou detalhes que não queira exibir considerando que será listado por more ou cat ou mesmo tac. Aparentemente, tais utilitários constroem a tela quando exibem arquivos.
  • Um mau uso (se fosse possível) é explorar o poder dos demais caracteres não imprimíveis para que execute comandos, simplesmente por listar um arquivo texto "preparado" (algo utópico).

Fica o relato desta surpresa evidenciando alguns utilitários bastante úteis para a linha de comando do terminal:

  • hexdump: exibição detalhada de um arquivo. Com as chaves adequadas, permite exibições personalizadas em relação à canônica.

  • xxd: não somente faz a exibição, mas com as chaves adequadas converte um conteúdo para sua representação em bytes ou bits. Possibilita a reversão de uma sequência de bytes para o correspondente binário (não se aplica a bits).

Prova de conceito
1) Criar um arquivo de amostra
$ echo -ne "distance zero crystal noise potato helmet coil dgiant add hip sting fancy 0509;2045;0426;1198;1350;0855 0362;0781;0025;0863;1711;0663 3FBFF4D54AEA8CD5CB530D32D7F57A97" | sed 's/ /\r/g' > sample.txt
2) Listar o tamanho do arquivo "sample.txt"
$ l
901 4 -rw-rw-r-- 1 1000 1000 1000 ? 166 2024-12-01 03:12:58.290966198 -0300 sample.txt

ou

$ wc sample.txt 
  0  15 166 sample.txt

ou

$ stat sample.txt 
  File: sample.txt
  Size: 166       	Blocks: 8          IO Block: 4096   regular file
Device: 1ah/26d	Inode: 901         Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/    usr)   Gid: ( 1000/    usr)
Access: 2024-12-01 03:35:15.825149271 -0300
Modify: 2024-12-01 03:12:58.290966198 -0300
Change: 2024-12-01 03:12:58.290966198 -0300
 Birth: -

ou várias outras possíveis soluções utilizando aliases...

Alias para `ls` com parâmetros extras
$ alias l='alias l='ls -m -tCl --almost-all --author --classify --context --color=always --escape --full-time --group-directories-first --inode --kibibytes --numeric-uid-gid --reverse --size''
4) Exibir o conteúdo dos arquivos com os utilitários
cat
$ cat sample.txt
3FBFF4D54AEA8CD5CB530D32D7F57A97
more
$ more sample.txt
3FBFF4D54AEA8CD5CB530D32D7F57A97
hexdump
$ hexdump -Cv sample.txt 
00000000  64 69 73 74 61 6e 63 65  0d 7a 65 72 6f 0d 63 72  |distance.zero.cr|
00000010  79 73 74 61 6c 0d 6e 6f  69 73 65 0d 70 6f 74 61  |ystal.noise.pota|
00000020  74 6f 0d 68 65 6c 6d 65  74 0d 63 6f 69 6c 0d 64  |to.helmet.coil.d|
00000030  67 69 61 6e 74 0d 61 64  64 0d 68 69 70 0d 73 74  |giant.add.hip.st|
00000040  69 6e 67 0d 66 61 6e 63  79 0d 30 35 30 39 3b 32  |ing.fancy.0509;2|
00000050  30 34 35 3b 30 34 32 36  3b 31 31 39 38 3b 31 33  |045;0426;1198;13|
00000060  35 30 3b 30 38 35 35 0d  30 33 36 32 3b 30 37 38  |50;0855.0362;078|
00000070  31 3b 30 30 32 35 3b 30  38 36 33 3b 31 37 31 31  |1;0025;0863;1711|
00000080  3b 30 36 36 33 0d 33 46  42 46 46 34 44 35 34 41  |;0663.3FBFF4D54A|
00000090  45 41 38 43 44 35 43 42  35 33 30 44 33 32 44 37  |EA8CD5CB530D32D7|
000000a0  46 35 37 41 39 37                                 |F57A97|
000000a6
xxd
$ xxd sample.txt 
00000000: 6469 7374 616e 6365 0d7a 6572 6f0d 6372  distance.zero.cr
00000010: 7973 7461 6c0d 6e6f 6973 650d 706f 7461  ystal.noise.pota
00000020: 746f 0d68 656c 6d65 740d 636f 696c 0d64  to.helmet.coil.d
00000030: 6769 616e 740d 6164 640d 6869 700d 7374  giant.add.hip.st
00000040: 696e 670d 6661 6e63 790d 3035 3039 3b32  ing.fancy.0509;2
00000050: 3034 353b 3034 3236 3b31 3139 383b 3133  045;0426;1198;13
00000060: 3530 3b30 3835 350d 3033 3632 3b30 3738  50;0855.0362;078
00000070: 313b 3030 3235 3b30 3836 333b 3137 3131  1;0025;0863;1711
00000080: 3b30 3636 330d 3346 4246 4634 4435 3441  ;0663.3FBFF4D54A
00000090: 4541 3843 4435 4342 3533 3044 3332 4437  EA8CD5CB530D32D7
000000a0: 4635 3741 3937                           F57A97

What do you see when you type http://localho.st into your browser's address bar and press [ENTER]?

[Keywords: cat, endline char, hexdump, surprises, utilities] // for [index|filter]ing purposes

Carregando publicação patrocinada...
3

Outra opção é usar cat -A arquivo, que mostra os caracteres invisíveis. No caso, o CR é mostrado como ^M, o TAB é ^I e o final da linha é marcado com $. Assim, vc consegue ver se tais caracteres estão presentes e se tem algo "estranho" no arquivo.

Se bem que o hexdump eu acho mais completo, pois mostra exatamente cada byte que está lá, evitando surpresas. Vai que tem algum outro caractere não imprimível - graças ao Unicode, a lista não é pequena, e muitos não são mostrados de um jeito bonito pelo cat.

Enfim, é interessante usar algum desses comandos pra vc ter certeza do que tem lá, assim vc saberá qual programa usar para converter (mac2unix, dos2unix, etc).

2

Quem nunca não passou perrengue com editores distintos mostrando códigos diferentes do mesmo arquivo e perdeu tarde inteira por conta de uma bobagem. Muito útil esta postagem aqui!