Come controllare il tipo di file senza estensioni in Python?


87

Ho una cartella piena di file e non hanno un'estensione. Come posso controllare i tipi di file? Voglio controllare il tipo di file e modificare il nome del file di conseguenza. Supponiamo che una funzione filetype(x)restituisca un tipo di file come png. Voglio farlo:

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

Come faccio a fare questo?



Dovrai essere più specifico riguardo a file types. Intendi determinare se è un gif, png, bmp o jpg? Vuoi solo sapere se è testo / binario? Eseguibile?
JoeFish

@ thg435, una volta che hai il tipo MIME, c'è un modo per convertirlo in un'estensione del nome file adatta?
Mark Ransom

@Mark: sì, usa guess_extension , ma in realtà, i mimetypes non funzioneranno qui, perché si basano sulle estensioni di file. Quello di cui hanno bisogno è libmagic (vedi la seconda risposta sul link).
georg

1
provare questo pypi.org/project/filetype ?
zx1986

Risposte:


92

Esistono librerie Python in grado di riconoscere i file in base al loro contenuto (solitamente un'intestazione / numero magico) e che non si basano sul nome o sull'estensione del file.

Se stai affrontando molti tipi di file diversi, puoi usare python-magic. Questo è solo un binding Python per la magiclibreria consolidata . Questo ha una buona reputazione e (piccola approvazione) nell'uso limitato che ne ho fatto, è stato solido.

Esistono anche librerie per tipi di file più specializzati. Ad esempio, la libreria standard di Python ha il imghdrmodulo che fa la stessa cosa solo per i tipi di file immagine.

Se è necessario il controllo del tipo di file senza dipendenze (puro Python), vedere filetype.


2
Il pacchetto ha python-magic-win64funzionato per me in Windows
ChesuCR

2
imghdr con combinazione di tipo di file ha funzionato per me in Windows
Hrushikesh Dhumal

62

La libreria Python Magic fornisce le funzionalità di cui hai bisogno.

È possibile installare la libreria pip install python-magice utilizzarla come segue:

>>> 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'

Il codice Python in questo caso chiama libmagic sotto il cofano, che è la stessa libreria usata dal filecomando * NIX . Quindi, questo fa la stessa cosa delle risposte basate su sottoprocesso / shell, ma senza quel sovraccarico.


6
Attenzione che il pacchetto debian / ubuntu chiamato python-magic è diverso dal pacchetto pip con lo stesso nome. Entrambi hanno import magicperò contenuti incompatibili. Vedi stackoverflow.com/a/16203777/3189 per ulteriori informazioni.
Hamish Downer

1
@Richard Ti dispiace elaborare l'aspetto generale? Cosa rende la python-magiclibreria più efficiente rispetto all'utilizzo di approcci di sottoprocesso?
Greg

9

Su Unix e Linux c'è il filecomando per indovinare i tipi di file. C'è anche una porta per Windows .

Dalla pagina man :

File verifica ogni argomento nel tentativo di classificarlo. Ci sono tre serie di test, eseguiti in questo ordine: test del file system, test dei numeri magici e test del linguaggio. Il primo test che ha esito positivo provoca la stampa del tipo di file.

Avresti bisogno di eseguire il filecomando con il subprocessmodulo e quindi analizzare i risultati per capire un'estensione.

modifica: ignora la mia risposta. Usa invece la risposta di Chris Johnson .


+1 Non mi ero reso conto di aver filefatto molto. # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
JoeFish

Beh, speravo che qualcuno avesse una risposta migliore. C'è ancora molto lavoro per l'OP, non è una semplice chiamata di funzione.
Steven Rumbalski

2
+1 Un vantaggio dell'utilizzo del filecomando è che è nativo su (la maggior parte?) Delle distribuzioni Linux mentre non lo python-magicè e deve essere scaricato e installato prima di poter essere utilizzato. Questo è un po 'un problema se si suppone che lo script che utilizza il modulo sia portabile.
Ciao Arrivederci


6

Puoi anche installare l' fileassociazione ufficiale per Python, una libreria chiamata file-magic(non usa ctypes, come python-magic).

È disponibile su PyPI come file-magic e su Debian come python-magic . Per me questa libreria è la migliore da usare poiché è disponibile su PyPI e su Debian (e probabilmente altre distribuzioni), rendendo più semplice il processo di distribuzione del software. Ho anche scritto sul blog come usarlo .


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

Come ha sottolineato Steven, subprocessè la via. È possibile ottenere l'output del comando per la via di cui sopra in quanto questo messaggio , ha detto


E come catturi l'output?
Mark Ransom

@MarkRansom mi dispiace che non sia stato un buon modo, per favore vedi i miei aggiornamenti sopra
xvatar

Se è necessario interagire con il proprio sistema invece di utilizzare una libreria Python, la soluzione non è ottimale per la maggior parte del tempo, perché probabilmente non è utile in altri sistemi operativi con un'API diversa.
erikbwork

4

Con la nuova libreria dei processi secondari, ora puoi utilizzare il codice seguente (soluzione solo * 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

Grazie per la risposta. BTW, non dovresti usare str.split () su una riga cmd. usa shlex.split (cmd) insteed.
emnoor

Invece di usare shlex.split, perché non correre subprocess.check_output(['file', '--mime-type', filename])?
Flimm

1

inoltre puoi usare questo codice (puro python da 3 byte di file di intestazione):

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"

senza alcun pacchetto di installazione [e aggiornamento della versione]


Come posso verificare la presenza di xlsx?
Harsha Biyani

È possibile utilizzare da 4 o 8 byte. XLSX (MS Office Open XML Format Document) => 50 4B 03 04 (4 byte) => ASCII (PK ••) o XLSX (documenti MS Office 2007) => 50 4B 03 04 14 00 06 00 (8 byte) = > ASCII (PK ••••••)
evergreen

0

Funziona solo per Linux ma usando il modulo python "sh" puoi semplicemente chiamare qualsiasi comando della shell

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

pip install sh

import sh

sh.file ("/ root / file")

Output: / root / file: testo ASCII

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.