Comment vérifier le type de fichiers sans extensions en python?

87

J'ai un dossier plein de fichiers et ils n'ont pas d'extension. Comment puis-je vérifier les types de fichiers? Je veux vérifier le type de fichier et changer le nom de fichier en conséquence. Supposons qu'une fonction filetype(x)renvoie un type de fichier comme png. Je veux faire ça:

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

Comment puis-je faire cela?

emnoor
la source
Vous devrez être plus précis en ce qui concerne file types. Voulez-vous dire déterminer s'il s'agit d'un gif, png, bmp ou jpg? Voulez-vous juste savoir s'il s'agit de texte / binaire? Exécutable?
JoeFish
@ thg435, une fois que vous avez le type MIME, y a-t-il un moyen de le convertir en une extension de nom de fichier appropriée?
Mark Ransom
@Mark: oui, utilisez guess_extension , mais en fait, les types MIME ne fonctionneront pas ici, car ils sont basés sur des extensions de fichiers. Ce dont ils ont besoin est libmagic (voir la 2ème réponse sur le lien).
georg
1
essayez ce pypi.org/project/filetype ?
zx1986

Réponses:

89

Il existe des bibliothèques Python qui peuvent reconnaître les fichiers en fonction de leur contenu (généralement un en-tête / numéro magique) et qui ne dépendent pas du nom ou de l'extension du fichier.

Si vous vous adressez à de nombreux types de fichiers différents, vous pouvez utiliser python-magic. C'est juste une liaison Python pour la magicbibliothèque bien établie . Cela a une bonne réputation et (petite approbation) dans l'usage limité que j'en ai fait, il a été solide.

Il existe également des bibliothèques pour des types de fichiers plus spécialisés. Par exemple, la bibliothèque standard Python a le imghdrmodule qui fait la même chose uniquement pour les types de fichiers image.

Si vous avez besoin d'une vérification du type de fichier sans dépendance (pur Python), voir filetype.

Chris Johnson
la source
2
Le package a python-magic-win64fonctionné pour moi dans Windows
ChesuCR
2
imghdr avec combinaison de type de fichier a fonctionné pour moi dans Windows
Hrushikesh Dhumal
61

La bibliothèque Python Magic fournit les fonctionnalités dont vous avez besoin.

Vous pouvez installer la bibliothèque avec pip install python-magicet l'utiliser comme suit:

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

Le code Python dans ce cas appelle à libmagic sous le capot, qui est la même bibliothèque utilisée par la filecommande * NIX . Ainsi, cela fait la même chose que les réponses basées sur le sous-processus / shell, mais sans cette surcharge.

Richard
la source
6
Attention, le package debian / ubuntu appelé python-magic est différent du package pip du même nom. Les deux sont import magicmais ont un contenu incompatible. Voir stackoverflow.com/a/16203777/3189 pour en savoir plus.
Hamish Downer
1
@Richard Cela vous dérange-t-il d'élaborer sur l'aspect des frais généraux? Qu'est-ce qui rend la python-magicbibliothèque plus efficace que l'utilisation d'approches de sous-processus?
Greg
9

Sous Unix et Linux, il existe une filecommande pour deviner les types de fichiers. Il y a même un port Windows .

Depuis la page de manuel :

File teste chaque argument pour tenter de le classer. Il existe trois ensembles de tests, effectués dans cet ordre: les tests du système de fichiers, les tests de nombres magiques et les tests de langage. Le premier test qui réussit entraîne l'impression du type de fichier.

Vous devrez exécuter la filecommande avec le subprocessmodule, puis analyser les résultats pour trouver une extension.

edit: Ignorez ma réponse. Utilisez plutôt la réponse de Chris Johnson .

Steven Rumbalski
la source
+1 Je n'avais pas réalisé fileque j'avais fait autant. # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
JoeFish
Eh bien, j'espérais que quelqu'un aurait une meilleure réponse. Il y a encore beaucoup de travail pour l'OP, ce n'est pas un simple appel de fonction.
Steven Rumbalski
2
+1 Un avantage de l'utilisation de la filecommande est qu'elle est native sur (la plupart?) Des distributions Linux alors que ne l' python-magicest pas et doit être téléchargée et installée avant de pouvoir être utilisée. C'est un peu un problème si le script utilisant le module est censé être portable.
HelloGoodbye
7

Dans le cas des images, vous pouvez utiliser le imghdrmodule.

>>> 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
la source
6

Vous pouvez également installer la fileliaison officielle pour Python, une bibliothèque appelée file-magic(elle n'utilise pas de ctypes, comme python-magic).

Il est disponible sur PyPI en tant que file-magic et sur Debian en tant que python-magic . Pour moi, cette bibliothèque est la meilleure à utiliser car elle est disponible sur PyPI et sur Debian (et probablement d'autres distributions), ce qui facilite le processus de déploiement de votre logiciel. J'ai également blogué sur la façon de l'utiliser .

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

Comme Steven l'a souligné, subprocessc'est le chemin. Vous pouvez obtenir la sortie de commande de la manière ci - dessus ce poste dit

xvatar
la source
Et comment capturer la sortie?
Mark Ransom
@MarkRansom désolé ce n'était pas un bon moyen, s'il vous plaît voir mes mises à jour ci
xvatar
Si vous avez besoin d'interagir avec votre système au lieu d'utiliser une bibliothèque Python, la solution est la plupart du temps sous-optimale, car elle n'est probablement pas utile dans d'autres systèmes d'exploitation avec une API différente.
erikbwork
4

Avec la nouvelle bibliothèque de sous-processus, vous pouvez désormais utiliser le code suivant (solution * nix uniquement):

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
la source
Merci d'avoir répondu. BTW, vous ne devriez pas utiliser un str.split () sur une ligne cmd. utilisez shlex.split (cmd) insteed.
emnoor
Au lieu d'utiliser shlex.split, pourquoi ne pas simplement courir subprocess.check_output(['file', '--mime-type', filename])?
Flimm
1

vous pouvez également utiliser ce code (python pur par 3 octets de fichier d'en-tête):

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"

sans aucune installation de package [et mise à jour de la version]

à feuilles persistantes
la source
Comment puis-je vérifier xlsx?
Harsha Biyani
Vous pouvez utiliser par 4 ou 8 octets. XLSX (document au format MS Office Open XML) => 50 4B 03 04 (4 octets) => ASCII (PK ••) ou XLSX (documents MS Office 2007) => 50 4B 03 04 14 00 06 00 (8 octets) = > ASCII (PK ••••••)
evergreen
0

Fonctionne uniquement pour Linux mais en utilisant le module python "sh", vous pouvez simplement appeler n'importe quelle commande shell

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

pip installer sh

importer sh

sh.file ("/ racine / fichier")

Sortie: / root / file: texte ASCII

Lelouch
la source