Como posso obter as extensões de um arquivo com base em seu conteúdo?

Como posso obter as extensões de um arquivo com base em seu conteúdo?

Estou planejando baixar um monte de imagens de um site que não vem com extensão, então quero adicionar uma com base no conteúdo do arquivo ou no tipo MIME.

file <filename>faz um ótimo trabalho na identificação do tipo de arquivo, porém preciso da extensão.

--extension
      Print a slash-separated list of valid extensions for the file type found.

Isto é da filepágina de manual de, mas parece não funcionar:

$ file --extension test_text_file.txt
test_text_file.txt: ???

$ file --extension test_png_file.png
test_png_file.png: ???

$ file --extension test_gif_file.gif
test_gif_file.gif: ???

Ele literalmente imprime ???para cada arquivo que eu passo para ele, mesmo aqueles que já possuem uma extensão adequada. Todos esses são arquivos válidos de seus tipos e são reconhecidos perfeitamente filesem a extensão --extension.

Por que file --extensionnão funciona para mim e o que posso usar para obter a extensão de um arquivo?

Uma idéia seria usar file --mime-typee criar uma matriz de tabela de despacho que mapeie tipos MIME conhecidos para suas extensões, mas prefiro uma solução mais simples e segura.

Responder1

Por que file --extensionnão funciona para mim?

Não só para você. Veressa questão. Um dos comentários parece certo:

Talvez apenas um recurso muito, muito incompleto?

Não encontrei nenhuma ferramenta Unix padrão para fazer a conversão, então sua ideia pode ser a solução mais fácil de qualquer maneira.

Uma idéia seria usar file --mime-typee criar uma matriz de tabela de despacho que mapeie tipos MIME conhecidos para suas extensões, mas prefiro uma solução mais simples e segura.

Observe que tal mapa existe, é /etc/mime.types. Veresta outra pergunta sobre Unix e Linux SE. Com base em uma das respostas, criei a seguinte função:

function getext() {
   [ "$#" != 1 ] && { echo "Wrong number of arguments. Provide exactly one." >&2; return 254; }
   [ -r "$1" ] || { echo "Not a file, nonexistent or unreadable." >&2; return 1; }
   grep "^$(file -b --mime-type "$1")"$'\t' /etc/mime.types |
      awk -F '\t+' '{print $2}'
}

Uso:

getext test_text_file.txt   # it takes just one argument

Adapte-o às suas necessidades, crie um script etc. As principais preocupações:

  • Se for bem-sucedido (exit status 0), a saída pode ser não vazia ou vazia (nem par \n).
  • Alguns tipos MIME retornam mais de uma extensão. Você pode usar cut -d ' ' -f 1para obter no máximo um, mas pode não ser o que você deseja.
  • Portanto, um arquivo de mapa personalizado /etc/mime.typespode ser útil. Este comando mostrará quais tipos MIME existem no diretório atual (e subdiretórios):

    find . -type f -exec file -b --mime-type {} + | sort | uniq
    
  • grepnão deve corresponder mais de uma vez (pelo menos com /etc/mime.types); ^(line start) e $'\t'(tab) existem para evitar correspondência parcial. Use grep -m 1 ...(ou head -n 1posterior) para ter certeza de obter no máximo uma linha.

Responder2

Vale a pena mencionar que ele mostra a extensão para alguns tipos de arquivo

file --preserve-date --special-files --extension *

Resultado:

BMP_file:          ???
CPP_file:          ???
FIFO_file:         ERROR: (null)
GZ_file:           ???
HAR_file:          ???
H_file:            ???
HTML_file:         ???
JAR_file:          zip/cbz
JAVA_CLASS_file:   ???
JAVA_JAVA_file:    ???
JPG_file:          jpeg/jpg/jpe/jfif
MKV_file:          ???
MP3_file:          ???
MP4_file:          ???
ODT_file:          ???
PDF_file:          ???
PNG_file:          ???
PPS_file:          ???
SHELL_SCRIPT_file: ???
SO_file:           ???
TIFF_file:         ???
TMP_file_GBQcW:    ???
XML_file:          ???
ZIP_file:          zip/cbz

informação relacionada