Wie überprüfe ich den Dateityp ohne Erweiterungen in Python?

84

Ich habe einen Ordner voller Dateien und sie haben keine Erweiterung. Wie kann ich Dateitypen überprüfen? Ich möchte den Dateityp überprüfen und den Dateinamen entsprechend ändern. Nehmen wir an, eine Funktion filetype(x)gibt einen Dateityp wie zurück png. Ich möchte das machen:

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

Wie mache ich das?

emnoor
quelle
Sie müssen in Bezug auf genauer sein file types. Meinen Sie damit, festzustellen, ob es sich um ein GIF, PNG, BMP oder JPG handelt? Möchten Sie nur wissen, ob es sich um Text / Binär handelt? Ausführbar?
JoeFish
@ thg435, gibt es nach dem MIME-Typ eine Möglichkeit, diesen in eine geeignete Dateinamenerweiterung zu konvertieren?
Mark Ransom
@Mark: Ja, benutze rate_extension , aber tatsächlich funktionieren Mimetypen hier nicht, da sie auf Dateierweiterungen basieren. Was sie brauchen, ist libmagisch (siehe die 2. Antwort auf dem Link).
Georg
1
Versuchen Sie dies pypi.org/project/filetype ?
zx1986

Antworten:

86

Es gibt Python-Bibliotheken, die Dateien anhand ihres Inhalts erkennen können (normalerweise eine Kopfzeile / magische Zahl) und sich nicht auf den Dateinamen oder die Dateierweiterung verlassen.

Wenn Sie viele verschiedene Dateitypen ansprechen, können Sie verwenden python-magic. Das ist nur eine Python-Bindung für die etabliertenmagic Bibliothek. Dies hat einen guten Ruf und (kleine Bestätigung) in der begrenzten Verwendung, die ich davon gemacht habe, war es solide.

Es gibt auch Bibliotheken für speziellere Dateitypen. Zum Beispiel hat die Python-Standardbibliothek dieimghdr Modul, das nur für Bilddateitypen dasselbe tut.

Wenn Sie eine abhängigkeitsfreie (reine Python-) Dateitypprüfung benötigen, lesen Sie filetype.

Chris Johnson
quelle
2
Das Paket python-magic-win64funktionierte für mich in Windows
ChesuCR
2
imghdr mit Kombination von Dateityp arbeitete für mich in Windows
Hrushikesh Dhumal
60

Die Python Magic- Bibliothek bietet die Funktionen, die Sie benötigen.

Sie können die Bibliothek mit installieren pip install python-magicund wie folgt verwenden:

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

Der Python-Code ruft in diesem Fall libmagic unter der Haube auf. Dies ist dieselbe Bibliothek, die auch vom fileBefehl * NIX verwendet wird . Dies macht also dasselbe wie die auf Teilprozessen / Shell basierenden Antworten, jedoch ohne diesen Aufwand.

Richard
quelle
6
Beachten Sie, dass sich das Debian / Ubuntu-Paket namens Python-Magic vom gleichnamigen Pip-Paket unterscheidet. Beide sind import magicaber inkompatible Inhalte. Weitere Informationen finden Sie unter stackoverflow.com/a/16203777/3189 .
Hamish Downer
1
@Richard Stört es Sie, auf den Overhead-Aspekt einzugehen? Was macht die python-magicBibliothek effizienter als die Verwendung von Unterprozessansätzen?
Greg
9

Unter Unix und Linux gibt es den fileBefehl, Dateitypen zu erraten. Es gibt sogar einen Windows-Port .

Von der Manpage :

File testet jedes Argument, um es zu klassifizieren. Es gibt drei Testreihen, die in dieser Reihenfolge durchgeführt werden: Dateisystemtests, magische Zahlentests und Sprachtests. Der erste erfolgreiche Test bewirkt, dass der Dateityp gedruckt wird.

Sie müssten den fileBefehl mit dem subprocessModul ausführen und dann die Ergebnisse analysieren, um eine Erweiterung herauszufinden.

edit: Ignoriere meine Antwort. Verwenden Sie stattdessen die Antwort von Chris Johnson .

Steven Rumbalski
quelle
+1 Ich habe nicht bemerkt, filedass ich so viel getan habe. # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
JoeFish
Ich hatte gehofft, jemand hätte eine bessere Antwort. Es gibt noch viel Arbeit für das OP, es ist kein einfacher Funktionsaufruf.
Steven Rumbalski
2
+1 Ein Vorteil bei der Verwendung des fileBefehls besteht darin, dass er auf (den meisten?) Linux-Distributionen nativ ist, während dies python-magicnicht der Fall ist und heruntergeladen und installiert werden muss, bevor er verwendet werden kann. Dies ist ein Problem, wenn das Skript, das das Modul verwendet, portabel sein soll.
Hallo Goodbye
7

Bei Bildern können Sie das imghdrModul verwenden.

>>> import imghdr
>>> imghdr.what('8e5d7e9d873e2a9db0e31f9dfc11cf47')  # You can pass a file name or a file object as first param. See doc for optional 2nd param.
'png'

Python 2 imghdr doc
Python 3 imghdr doc

Lewis Diamond
quelle
6

Sie können auch die offizielle fileBindung für Python installieren , eine Bibliothek namens file-magic(sie verwendet keine ctypes, wie python-magic).

Es ist auf PyPI als File-Magic und auf Debian als Python-Magic verfügbar . Für mich ist diese Bibliothek die beste, da sie auf PyPI und Debian (und wahrscheinlich auch auf anderen Distributionen) verfügbar ist, was die Bereitstellung Ihrer Software erleichtert. Ich habe auch darüber gebloggt, wie man es benutzt .

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

Wie Steven betonte, subprocessist der Weg. Sie können die Befehlsausgabe durch die Art und Weise oben erhalten , wie diese Post sagte

xvatar
quelle
Und wie erfassen Sie die Ausgabe?
Mark Ransom
@ MarkRansom Entschuldigung, das war kein guter Weg, siehe meine Updates oben
xvatar
Wenn Sie mit Ihrem System interagieren müssen, anstatt eine Python-Bibliothek zu verwenden, ist die Lösung die meiste Zeit nicht optimal, da sie in anderen Betriebssystemen mit einer anderen API wahrscheinlich nicht nützlich ist.
Erikbwork
4

Mit einer neueren Unterprozessbibliothek können Sie jetzt den folgenden Code verwenden (nur * nix-Lösung):

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
berniey
quelle
Danke für die Antwort. Übrigens sollten Sie kein str.split () in einer cmd-Zeile verwenden. Verwenden Sie shlex.split (cmd) insteed.
Emnoor
shlex.splitWarum nicht einfach laufen, anstatt zu verwenden subprocess.check_output(['file', '--mime-type', filename])?
Flimm
1

Sie können auch diesen Code verwenden (reines Python mit 3 Byte Header-Datei):

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"

ohne Paket installieren [und Version aktualisieren]

immergrün
quelle
Wie kann ich nach xlsx suchen?
Harsha Biyani
Sie können mit 4 oder 8 Bytes verwendet werden. XLSX (Dokument im offenen XML-Format von MS Office) => 50 4B 03 04 (4 Byte) => ASCII (PK ••) oder XLSX (Dokumente von MS Office 2007) => 50 4B 03 04 14 00 06 00 (8 Byte) = > ASCII (PK ••••••)
immergrün
0

Funktioniert nur unter Linux, aber mit dem Python-Modul "sh" können Sie einfach einen beliebigen Shell-Befehl aufrufen

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

pip install sh

import sh

sh.file ("/ root / file")

Ausgabe: / root / file: ASCII-Text

Lelouch
quelle