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.