Como verificar o tipo de arquivos sem extensões em python?


87

Tenho uma pasta cheia de arquivos e eles não têm extensão. Como posso verificar os tipos de arquivo? Desejo verificar o tipo de arquivo e alterá-lo de acordo. Vamos supor que uma função filetype(x)retorne um tipo de arquivo como png. Eu quero fazer isso:

files = os.listdir(".")
for f in files:
    os.rename(f, f+filetype(f))

Como eu faço isso?



Você terá que ser mais específico em relação a file types. Você quer dizer determinar se é um gif, png, bmp ou jpg? Quer apenas saber se é texto / binário? Executável?
— JoeFish

@ thg435, uma vez que você tenha o tipo MIME, há uma maneira de convertê-lo em uma extensão de nome de arquivo adequada?
— Mark Ransom

@Mark: sim, use guess_extension , mas na verdade, mimetypes não funcionam aqui, porque é baseado em extensões de arquivo. O que eles precisam é de libmagic (veja a 2ª resposta no link).
— georg

Respostas:


89

Existem bibliotecas Python que podem reconhecer arquivos com base em seu conteúdo (geralmente um cabeçalho / número mágico) e que não dependem do nome ou extensão do arquivo.

Se estiver lidando com muitos tipos de arquivos diferentes, você pode usar python-magic. Isso é apenas uma ligação Python para a magicbiblioteca bem estabelecida . Isso tem uma boa reputação e (pequeno endosso) no uso limitado que fiz dele, tem sido sólido.

Também existem bibliotecas para tipos de arquivos mais especializados. Por exemplo, a biblioteca padrão do Python possui o imghdrmódulo que faz a mesma coisa apenas para tipos de arquivo de imagem.

Se você precisar de verificação de tipo de arquivo livre de dependência (Python puro), consulte filetype.


2
O pacote python-magic-win64funcionou para mim no Windows
— ChesuCR

2
imghdr com combinação de tipo de arquivo funcionou para mim no Windows
— Hrushikesh Dhumal

61

A biblioteca Python Magic fornece a funcionalidade de que você precisa.

Você pode instalar a biblioteca pip install python-magice usá-la da seguinte maneira:

>>> import magic

>>> magic.from_file('iceland.jpg')
'JPEG image data, JFIF standard 1.01'

>>> magic.from_file('iceland.jpg', mime=True)
'image/jpeg'

>>> magic.from_file('greenland.png')
'PNG image data, 600 x 1000, 8-bit colormap, non-interlaced'

>>> magic.from_file('greenland.png', mime=True)
'image/png'

O código Python, neste caso, está chamando libmagic por baixo do capô, que é a mesma biblioteca usada pelo filecomando * NIX . Portanto, isso faz a mesma coisa que as respostas baseadas em subprocesso / shell, mas sem essa sobrecarga.


6
Esteja ciente de que o pacote debian / ubuntu chamado python-magic é diferente do pacote pip de mesmo nome. Ambos são, import magicmas têm conteúdos incompatíveis. Consulte stackoverflow.com/a/16203777/3189 para obter mais informações.
— Hamish Downer

1
@Richard Você se importa em elaborar sobre o aspecto geral? O que torna a python-magicbiblioteca mais eficiente do que usar abordagens de subprocesso?
— Greg

9

No Unix e no Linux, existe o filecomando para adivinhar os tipos de arquivo. Há até uma porta do Windows .

Na página de manual :

O arquivo testa cada argumento na tentativa de classificá-lo. Existem três conjuntos de testes, executados nesta ordem: testes de sistema de arquivos, testes de número mágico e testes de idioma. O primeiro teste bem-sucedido faz com que o tipo de arquivo seja impresso.

Você precisaria executar o filecomando com o subprocessmódulo e, em seguida, analisar os resultados para descobrir uma extensão.

editar: Ignore minha resposta. Use a resposta de Chris Johnson .


1 Eu não sabia fileque fiz muito. # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
— JoeFish

Bem, eu esperava que alguém tivesse uma resposta melhor. Ainda há muito trabalho para o OP, não é uma simples chamada de função.
— Steven Rumbalski

2
+1 Um benefício de usar o filecomando é que ele é nativo na (maioria?) Distribuições Linux, enquanto o python-magicnão é e deve ser baixado e instalado antes de ser usado. Isso é um tanto problemático se o script que usa o módulo for portátil.
— HelloGoodbye


6

Você também pode instalar a fileligação oficial para Python, uma biblioteca chamada file-magic(ela não usa ctypes, como python-magic).

Ele está disponível no PyPI como arquivo mágico e no Debian como python-mágico . Para mim, esta biblioteca é a melhor para usar, pois está disponível no PyPI e no Debian (e provavelmente em outras distribuições), tornando o processo de implantação do seu software mais fácil. Também fiz um blog sobre como usá-lo .


6
import subprocess
p = sub.Popen('file yourfile.txt', stdout=sub.PIPE, stderr=sub.PIPE)
output, errors = p.communicate()
print(output)

Como Steven apontou, subprocessé o caminho. Você pode obter a saída do comando acima como este post disse


E como você captura a saída?
— Mark Ransom

@MarkRansom, desculpe, não foi uma boa maneira, por favor, veja minhas atualizações acima
— xvatar

Se você precisa interagir com seu sistema em vez de usar uma biblioteca Python, a solução é subótima na maioria das vezes, porque provavelmente não é útil em outros sistemas operacionais com uma API diferente.
— erikbwork

4

Com a biblioteca de subprocesso mais recente, agora você pode usar o seguinte código (solução apenas * nix):

import subprocess
import shlex

filename = 'your_file'
cmd = shlex.split('file --mime-type {0}'.format(filename))
result = subprocess.check_output(cmd)
mime_type = result.split()[-1]
print mime_type

Obrigado pela resposta. BTW, você não deve usar str.split () em uma linha cmd. use shlex.split (cmd) insteed.
— emnoor

Em vez de usar shlex.split, por que não apenas correr subprocess.check_output(['file', '--mime-type', filename])?
— Flimm

1

também você pode usar este código (python puro por 3 bytes de arquivo de cabeçalho):

full_path = os.path.join(MEDIA_ROOT, pathfile)

try:
    image_data = open(full_path, "rb").read()
except IOError:
    return "Incorrect Request :( !!!"

header_byte = image_data[0:3].encode("hex").lower()

if header_byte == '474946':
    return "image/gif"
elif header_byte == '89504e':
    return "image/png"
elif header_byte == 'ffd8ff':
    return "image/jpeg"
else:
    return "binary file"

sem qualquer pacote de instalação [e versão de atualização]


Como posso verificar se há xlsx?
— Harsha Biyani

Você pode usar por 4 ou 8 bytes. XLSX (Documento de formato MS Office Open XML) => 50 4B 03 04 (4 Bytes) => ASCII (PK ••) ou XLSX (documentos do MS Office 2007) => 50 4B 03 04 14 00 06 00 (8 Bytes) = > ASCII (PK ••••••)
— evergreen

0

Só funciona para Linux, mas usando o módulo "sh" python você pode simplesmente chamar qualquer comando shell

https://pypi.org/project/sh/

pip instalar sh

importar sh

sh.file ("/ root / arquivo")

Saída: / root / arquivo: texto ASCII

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.