Como os tipos de arquivo são conhecidos, se não do sufixo do arquivo?

55

Gostaria de saber como os tipos de arquivo são conhecidos se os nomes de arquivos não tiverem sufixos.

Por exemplo, um arquivo nomeado myfilepode ser binário ou texto, como o sistema sabe se o arquivo é binário ou texto?

Niklas Rosencrantz
fonte
3
Apenas um comentário, o restante das respostas cobre tudo. Atualmente, pode acontecer que, com um código de idioma configurado incorretamente ou com executáveis ​​antigos, alguns arquivos utf-8 possam ser mal detectados como dados binários devido a bytes não ascii.
Orion
19
O sistema não se importa. Certos aplicativos podem se importar, mas cada um tem suas próprias maneiras de lidar com isso.
jwodder
2
Observe que mesmo para arquivos regulares (não arquivos de dispositivo, soquetes de domínio unix, pipes nomeados etc.) "tipo de arquivo" pode significar duas coisas diferentes: (1) um formato de arquivo específico (".docx", XML, formato de texto MS-DOS , RTF, registros de tamanho fixo, a lista pode ser muito longa) ou (2) Um arquivo com o qual um aplicativo específico sabe como lidar (".xlsx" ou ".doc" ou o que for, há sobreposição com o tipo de formato) . Vale a pena lembrar essa distinção ao falar sobre "tipo de arquivo".
precisa
@jwodder O sistema se importa. É o sistema que reclama que você não pode executar um arquivo não executável quando tenta, não esses aplicativos!
Lister
11
@MrLister True, mas executável / não executável não tem nada a ver com 'extensão'.
user2338816

Respostas:

84

O fileutilitário determina o tipo de arquivo de três maneiras:

Primeiro, o sistema de arquivos testa : Nesses testes, uma das chamadas do sistema da família stat é chamada no arquivo. Isso retorna os diferentes tipos de arquivo unix : arquivo regular, diretório, link, dispositivo de caractere, dispositivo de bloco, pipe nomeado ou um soquete. Dependendo disso, os testes de mágica são feitos.

Os testes de mágica são um pouco mais complexos. Os tipos de arquivo são adivinhados por um banco de dados de padrões chamado arquivo mágico . Alguns tipos de arquivos podem ser determinados lendo um bit ou número em um local específico dentro do arquivo (binários, por exemplo). O arquivo mágico contém " números mágicos " para testar se ele os contém ou não e quais informações de texto devem ser impressas. Esses " números mágicos " podem ter valores de 1 a 4Byte, seqüências de caracteres, datas ou mesmo expressões regulares. Com outros testes, informações adicionais podem ser encontradas. No caso de um executável, informações adicionais seriam vinculadas ou não dinamicamente , removidasou não ou a arquitetura. Às vezes, vários testes devem passar antes que o tipo de arquivo possa ser realmente identificado. De qualquer forma, não importa quantos testes são executados, é sempre apenas um bom palpite .

Aqui estão os primeiros 8 bytes em um arquivo de alguns tipos de arquivos comuns que podem nos ajudar a ter uma ideia de como esses números mágicos podem se parecer:

             Hexadecimal          ASCII
PNG   89 50 4E 47|0D 0A 1A 0A   ‰PNG|....
JPG   FF D8 FF E1|1D 16 45 78   ÿØÿá|..Ex
JPG   FF D8 FF E0|00 10 4A 46   ÿØÿà|..JF
ZIP   50 4B 03 04|0A 00 00 00   PK..|....
PDF   25 50 44 46|2D 31 2E 35   %PDF|-1.5

Se o tipo de arquivo não puder ser encontrado nos testes mágicos, o arquivo parecerá um arquivo de texto e fileprocurará a codificação do conteúdo. A codificação é diferenciada pelos diferentes intervalos e sequências de bytes que constituem texto imprimível em cada conjunto.

As quebras de linha também são investigadas, dependendo de seus valores HEX:

  • 0A( \n) classifica um arquivo finalizado Un * x / Linux / BSD / OSX
  • 0D 0A( \r\n) são arquivos de sistemas operacionais Microsoft
  • 0D( \r) seria o Mac OS até a versão 9
  • 15( \025) seria IBMs AIX

Agora os testes de idioma começam. Se parece ser um arquivo de texto, o arquivo é pesquisado por sequências específicas para descobrir qual idioma ele contém (C, Perl, Bash). Algumas linguagens de script também podem ser identificadas sobre o hashbang ( #!/bin/interpreter) na primeira linha do script.

Se nada se aplica ao arquivo, o tipo de arquivo não pode ser determinado e fileapenas imprime "dados".

Então, você vê que não há necessidade de um sufixo. Um sufixo de qualquer maneira pode confundir, se definido incorretamente.

caos
fonte
4
Há também o banco de dados MIME compartilhado do freedesktop.org, usado por praticamente todos os aplicativos X11. Isso é semelhante em conceito ao que file(1)faz, mas com uma implementação (muito) diferente.
Lcd047 /
4
Observe que o resultado desse processo é basicamente um palpite e não deve ser considerado algo importante. (Características de conveniência, como decidir o programa padrão para abrir o arquivo com, são muito bem)
user253751
Portanto, se eu adicionar% PNG na parte superior de um arquivo de texto, ele será visto como um arquivo png. Direito??
Saga
@saga Se você acertar a codificação e colocar um sinal de mille ao invés de um por cento, talvez: talvez. Pode haver testes adicionais.
Bananguin
19

Muitas vezes, isso não se importa. Você apenas o passa para um programa e ele o interpreta ou não. Pode não ser útil abrir um .jpg em um editor de texto, mas você não é impedido de fazer isso. A extensão, como o restante do nome do arquivo, é para a conveniência organizacional dos seres humanos.

Também pode ser possível construir arquivos que possam ser validamente interpretados de várias maneiras. Como o formato do arquivo ZIP inicia, possui um cabeçalho no final do arquivo , você pode acrescentar outras coisas à frente e ele ainda será carregado como um arquivo ZIP. Isso é comumente usado para criar arquivos zip com extração automática.

pjc50
fonte
4
No último parágrafo: Funky File Formats é uma palestra interessante sobre esse assunto, apresentando, por exemplo, um jpeg que também é um programa java hello world, depois de o AES criptografá-lo, ele se torna um PNG ou, depois de descriptografá-lo, o 3DES se torna um PDF e muito mais ( todos com conteúdo "interessante", ou seja, não apenas com o ruído branco ou artefactos)
Hagen von Eitzen
14

Essa informação é comumente encontrada no cabeçalho do arquivo. O filecomando analisa o destino e informa informações sobre o arquivo. Muitas informações são derivadas de cabeçalhos de arquivo, muitas vezes os primeiros bytes de um arquivo (veja abaixo). Os cabeçalhos são usados ​​pelo sistema para descobrir como lidar com arquivos. #!/bin/bashno início de um arquivo diz ao sistema para usar o shell bash para interpretar o seguinte script. ELFinforma ao sistema que este é um executável ELF.

[~] root@www # file /bin/ls
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

[~] root@www # file /etc/passwd
/etc/passwd: ASCII text

Exemplos de cabeçalho de arquivo:

[root@server4 ~]# xxd old_sm_logo.png | head -5
0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 0134 0000 006f 0806 0000 0062 bf3c  ...4...o.....b.<

[root@server4 ~]# xxd /bin/ls | head -5
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
0000010: 0200 3e00 0100 0000 a024 4000 0000 0000  ..>......$@.....

[root@server4 proj]# xxd resizer.sh | head -5
0000000: 2321 2f62 696e 2f62 6173 680a 5b20 2d7a  #!/bin/bash.[ -z
0000010: 2022 2431 2220 5d20 2626 2065 6368 6f20   "$1" ] && echo
h3rrmiller
fonte
3
Isso é bastante enganador. Os arquivos Unix não têm um "cabeçalho" em si. O filecomando tenta adivinhar, a partir do conteúdo do arquivo, como o arquivo provavelmente deve ser usado. Não é infalível.
Nate Eldredge #
Você está certo em como explicou o comportamento de file. De fato, faz uma análise do arquivo. No entanto, a maioria dos tipos de arquivos é identificada por um tipo de cabeçalho. 0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............é um cabeçalho de um executável ELF (primeiros bytes de / bin / ls). Da mesma forma, #!/bin/bashna parte superior de um arquivo ASCII, ele seria identificado como um script de shell. Outro exemplo: 0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR(a .png image)
h3rrmiller
2
Mas sua resposta faz parecer que um cabeçalho é um recurso inerente a um arquivo Unix. Arquivos de texto, por exemplo, não possuem esse cabeçalho; alguém como o OP provavelmente consideraria um arquivo de origem C e um arquivo de origem Java como tendo "tipos de arquivo" diferentes, mas não há cabeçalho para distingui-los. Eu argumentaria que "tipo de arquivo" nem sequer é um conceito significativo no Unix; o sistema operacional fornece apenas um sistema de arquivos e cabe a cada aplicativo decidir o que significa o conteúdo de qualquer arquivo.
Nate Eldredge
Concordo. Eu estava tentando responder da maneira mais simples possível sem descer por muitos buracos de coelho.
H3rrmiller
7

A primeira coisa a verificar é o tipo de arquivo codificado que é reconhecido pelo kernel. Esses são os tipos de arquivo, como diretório, arquivo especial de caractere, arquivo especial de bloco, arquivo especial de tubo, soquete e link simbólico. Esta informação vem do inode do arquivo. Se o arquivo for um arquivo simples, o próximo conjunto de informações virá dos primeiros 256 bytes, procurando por padrões. Assim, os arquivos de texto e o código fonte C são reconhecidos examinando esses bytes. Além disso, os utilitários também procuram um número mágico usado para testar e validar o tipo de arquivo. Você pode adicionar seus próprios tipos de arquivos a serem reconhecidos adicionando as informações ao arquivo /etc/magic. Consulte a página do manual para magic(5)ver o formato do arquivo mágico.

Na implementação mais antiga (Solaris, por exemplo), o arquivo /etc/magicenumerava a maioria dos tipos de arquivos reconhecidos.

unxnut
fonte
4

O filecomando aplica algumas heurísticas ao inspecionar (partes do) arquivo e fazer uma estimativa qualificada. Além disso, existem alguns casos especiais em que informações adicionais podem ser obtidas; como #!no início de um arquivo de texto, um BoM (byte order mark) ou bytes de cabeçalho específicos de formatos de arquivo executáveis. As #!marcas e binárias nos executáveis ​​são usadas pelo sistema para diferenciá-las.

Janis
fonte
4

O sistema não sabe se um arquivo é binário ou texto. Em todos os sistemas operacionais do tipo Unix (AFAIK), fopen(path, "rb")é exatamente o mesmo que fopen(path "r")- bnão tem efeito. É aceito porque o padrão C precisa ser portátil para outros sistemas operacionais que fazem essa distinção.

Toby Speight
fonte
0

Eu argumentaria que "tipo de arquivo" nem sequer é um conceito significativo no Unix;

Nos velhos tempos dos computadores mainframe, os SOs suportavam vários tipos de arquivos, incluindo seqüencial e sequencial de índice. Os sistemas operacionais modernos (Un * xe possivelmente o Windows) reduzem o conjunto de tipos de arquivo ao mínimo (incluindo objeto compartilhado e executável).

Também pode ser possível construir arquivos que possam ser validamente interpretados de várias maneiras

É possível, existe um formato de arquivo complicado: um pedaço de código C que pode ser interpretado como uma descrição da imagem. Além disso, existem diferentes formatos cada vez menos específicos: arquivo de texto, arquivo XML, um documento SOAP.

ijbalazs
fonte
11
Conforme os formatos de arquivo, o XPM não é tão complicado. Considero "complicado" começar com algo que é um JPEG válido e um arquivo ZIP válido.
Mark