Как проверить тип файлов без расширений в Python?

87

У меня есть папка, полная файлов, и у них нет расширения. Как я могу проверить типы файлов? Я хочу проверить тип файла и соответственно изменить имя файла. Предположим, функция filetype(x)возвращает тип файла, например png. Я хочу сделать это:

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

Как мне это сделать?

Emnoor
источник
Вы должны быть более конкретными в отношении file types. Вы имеете в виду определение формата GIF, PNG, BMP или JPG? Вы просто хотите знать, текст это / бинарный? Исполняемый?
JoeFish 07
@ thg435, если у вас есть тип MIME, есть ли способ преобразовать его в подходящее расширение имени файла?
Марк Рэнсом
@Mark: да, используйте guess_extension , но на самом деле mimetypes здесь не работают, потому что они основаны на расширениях файлов. Им нужна libmagic (см. Второй ответ по ссылке).
georg 07
1
попробуйте этот pypi.org/project/filetype ?
zx1986

Ответы:

89

Существуют библиотеки Python, которые могут распознавать файлы на основе их содержимого (обычно заголовка / магического числа) и не зависят от имени или расширения файла.

Если вы обращаетесь к разным типам файлов, вы можете использовать python-magic. Это просто привязка Python к хорошо зарекомендовавшей себя magicбиблиотеке. У этого есть хорошая репутация и (небольшое одобрение) в ограниченном использовании, которое я использовал, это было твердым.

Существуют также библиотеки для более специализированных типов файлов. Например, в стандартной библиотеке Python есть imghdrмодуль, который делает то же самое только для типов файлов изображений.

Если вам нужна проверка типов файлов без зависимостей (чистый Python), см filetype..

Крис Джонсон
источник
2
Пакет python-magic-win64работал у меня в Windows
ChesuCR
2
imghdr с комбинацией типов файлов работал у меня в окнах
Хрушикеш Дхумал
61

Библиотека Python Magic предоставляет необходимые вам функции.

Вы можете установить библиотеку pip install python-magicи использовать ее следующим образом:

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

Код Python в этом случае вызывает под капотом libmagic , которая является той же библиотекой, которая используется командой * NIX file. Таким образом, это делает то же самое, что и ответы на основе подпроцесса / оболочки, но без этих накладных расходов.

Ричард
источник
6
Помните, что пакет debian / ubuntu под названием python-magic отличается от пакета pip с тем же именем. Оба import magicимеют несовместимое содержимое. См. Stackoverflow.com/a/16203777/3189 для получения дополнительной информации.
Хэмиш Даунер
1
@ Ричард. Не могли бы вы подробнее остановиться на накладных расходах? Что делает python-magicбиблиотеку более эффективной, чем использование подпроцессных подходов?
Greg
9

В unix и linux есть fileкоманда угадывать типы файлов. Есть даже порт windows .

На странице руководства :

Файл проверяет каждый аргумент, пытаясь его классифицировать. Есть три набора тестов, выполняемых в указанном порядке: тесты файловой системы, тесты магических чисел и языковые тесты. Первый успешный тест приводит к печати типа файла.

Вам нужно будет запустить fileкоманду с subprocessмодулем, а затем проанализировать результаты, чтобы определить расширение.

изменить: игнорировать мой ответ. Вместо этого используйте ответ Криса Джонсона .

Стивен Румбальский
источник
+1 Я этого не понимал file. # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
JoeFish 07
Что ж, я надеялся, что у кого-то есть ответ получше. Для OP еще много работы, это не простой вызов функции.
Стивен Румбальский, 07
2
+1 Одно из преимуществ использования этой fileкоманды заключается в том, что она встроена в (большинство?) Дистрибутивов Linux, в то время python-magicкак ее нет, и ее необходимо загрузить и установить, прежде чем ее можно будет использовать. Это в некоторой степени проблема, если сценарий, использующий модуль, должен быть переносимым.
HelloGoodbye
7

В случае изображений вы можете использовать imghdrмодуль.

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

Льюис Даймонд
источник
6

Вы также можете установить официальную fileпривязку для Python, называемую библиотекой file-magic(она не использует ctypes, например python-magic).

Он доступен в PyPI как file-magic и в Debian как python-magic . Для меня лучше всего использовать эту библиотеку, поскольку она доступна в PyPI и Debian (и, возможно, в других дистрибутивах), что упрощает процесс развертывания вашего программного обеспечения. Я тоже писал в блоге о том, как его использовать .

Альваро Юстен
источник
6
import subprocess
p = sub.Popen('file yourfile.txt', stdout=sub.PIPE, stderr=sub.PIPE)
output, errors = p.communicate()
print(output)

Как указал Стивен, subprocessэто путь. Вы можете получить вывод команды указанным выше способом, как сказано в этом сообщении.

xvatar
источник
А как вы фиксируете вывод?
Марк Рэнсом
@MarkRansom извините, что это был не лучший способ, пожалуйста, посмотрите мои обновления выше
xvatar
Если вам нужно взаимодействовать с вашей системой вместо использования библиотеки Python, решение в большинстве случаев является неоптимальным, поскольку оно, вероятно, бесполезно в других операционных системах с другим API.
erikbwork
4

С новой библиотекой подпроцессов теперь вы можете использовать следующий код (решение только для * 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
Берни
источник
Спасибо за ответ. Кстати, вы не должны использовать str.split () в строке cmd. используйте shlex.split (cmd) insteed.
emnoor 06
Вместо того, чтобы использовать shlex.split, почему бы просто не запустить subprocess.check_output(['file', '--mime-type', filename])?
Flimm 03
1

также вы можете использовать этот код (чистый питон на 3 байта заголовочного файла):

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"

без установки пакета [и версии обновления]

вечнозеленый
источник
Как я могу проверить xlsx?
Харша Бияни
Можно использовать 4 или 8 байтов. XLSX (документ в формате MS Office Open XML) => 50 4B 03 04 (4 байта) => ASCII (PK ••) или XLSX (документы MS Office 2007) => 50 4B 03 04 14 00 06 00 (8 байтов) = > ASCII (PK ••••••)
вечнозеленый
0

Работает только для Linux, но с помощью модуля python "sh" вы можете просто вызвать любую команду оболочки.

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

pip install sh

импорт ш

sh.file ("/ корень / файл")

Вывод: / root / file: текст ASCII

Лелуш
источник