Bagaimana cara memeriksa jenis file tanpa ekstensi di python?

87

Saya memiliki folder yang penuh dengan file dan mereka tidak memiliki ekstensi. Bagaimana cara memeriksa jenis file? Saya ingin memeriksa jenis file dan mengubah nama file yang sesuai. Mari kita asumsikan suatu fungsi filetype(x)mengembalikan tipe file seperti png. Aku ingin melakukan ini:

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

Bagaimana saya melakukan ini?

emnoor
sumber
Anda harus lebih spesifik berkenaan dengan file types. Apakah maksud Anda menentukan apakah itu gif, png, bmp, atau jpg? Apakah Anda hanya ingin tahu apakah itu teks / biner? Dapat dieksekusi?
JoeFish
@ thg435, setelah Anda memiliki tipe MIME, apakah ada cara untuk mengubahnya menjadi ekstensi nama file yang sesuai?
Markus Tebusan
@Mark: ya, gunakan guess_extension , tetapi sebenarnya, mimetypes tidak akan berfungsi di sini, karena didasarkan pada ekstensi file. Yang mereka butuhkan adalah libmagic (lihat jawaban ke-2 di tautan).
georg
1
coba pypi.org/project/filetype ini ?
zx1986

Jawaban:

92

Ada pustaka Python yang dapat mengenali file berdasarkan kontennya (biasanya nomor header / ajaib) dan tidak bergantung pada nama file atau ekstensi.

Jika Anda menangani banyak jenis file yang berbeda, Anda dapat menggunakan python-magic. Itu hanya pengikatan Python untuk magicpustaka yang sudah mapan . Ini memiliki reputasi yang baik dan (dukungan kecil) dalam penggunaan terbatas yang saya buat, ini solid.

Ada juga perpustakaan untuk jenis file yang lebih khusus. Misalnya, pustaka standar Python memiliki imghdrmodul yang melakukan hal yang sama hanya untuk jenis file gambar.

Jika Anda memerlukan pemeriksaan jenis file bebas ketergantungan (Python murni), lihat filetype.

Chris Johnson
sumber
2
Paket ini python-magic-win64berfungsi untuk saya di Windows
ChesuCR
2
imghdr dengan kombinasi jenis file bekerja untuk saya di windows
Hrushikesh Dhumal
62

The Python Sihir perpustakaan menyediakan fungsi yang Anda butuhkan.

Anda dapat menginstal pustaka dengan pip install python-magicdan menggunakannya sebagai berikut:

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

Kode Python dalam hal ini memanggil ke libmagic di balik kap mesin, yang merupakan pustaka yang sama yang digunakan oleh perintah * NIX file. Jadi, ini melakukan hal yang sama sebagai jawaban berbasis subproses / shell, tetapi tanpa overhead itu.

Richard
sumber
6
Berhati-hatilah karena paket debian / ubuntu yang disebut python-magic berbeda dengan paket pip dengan nama yang sama. Keduanya import magicmemiliki konten yang tidak kompatibel. Lihat stackoverflow.com/a/16203777/3189 untuk lebih lanjut.
Hamish Downer
1
@Richard Apakah Anda keberatan menguraikan aspek overhead? Apa yang membuat python-magicperpustakaan lebih efisien daripada menggunakan pendekatan subproses?
Greg
9

Di unix dan linux ada fileperintah untuk menebak jenis file. Bahkan ada port windows .

Dari halaman manual :

File menguji setiap argumen dalam upaya untuk mengklasifikasikannya. Ada tiga rangkaian pengujian, yang dilakukan dalam urutan ini: pengujian sistem file, pengujian angka ajaib, dan pengujian bahasa. Tes pertama yang berhasil menyebabkan tipe file dicetak.

Anda perlu menjalankan fileperintah dengan subprocessmodul dan kemudian mengurai hasilnya untuk mengetahui ekstensi.

edit: Abaikan jawaban saya. Gunakan jawaban Chris Johnson sebagai gantinya.

Steven Rumbalski
sumber
+1 Saya tidak menyadari filemelakukan sebanyak itu. # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
JoeFish
Yah, saya berharap seseorang memiliki jawaban yang lebih baik. Masih banyak pekerjaan untuk OP, ini bukan pemanggilan fungsi sederhana.
Steven Rumbalski
2
+1 Satu keuntungan menggunakan fileperintah ini adalah perintah ini asli (kebanyakan?) Pada distribusi Linux sedangkan yang python-magictidak dan harus diunduh dan diinstal sebelum dapat digunakan. Ini agak menjadi masalah jika skrip yang menggunakan modul seharusnya portabel.
HelloGoodbye
7

Untuk gambar, Anda dapat menggunakan imghdrmodul.

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

Anda juga dapat menginstal filepengikatan resmi untuk Python, sebuah pustaka bernama file-magic(tidak menggunakan ctypes, seperti python-magic).

Ini tersedia di PyPI sebagai file-magic dan di Debian sebagai python-magic . Bagi saya library ini adalah yang terbaik untuk digunakan karena tersedia di PyPI dan Debian (dan mungkin distribusi lain), membuat proses penerapan perangkat lunak Anda lebih mudah. Saya juga membuat blog tentang cara menggunakannya .

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

Seperti yang ditunjukkan Steven, subprocessbegitulah caranya. Anda bisa mendapatkan output perintah dengan cara di atas seperti yang dikatakan posting ini

xvatar.dll
sumber
Dan bagaimana Anda menangkap hasilnya?
Markus Tebusan
@MarkRansom maaf itu bukan cara yang baik, silakan lihat pembaruan saya di atas
xvatar
Jika Anda perlu berinteraksi dengan sistem Anda alih-alih menggunakan pustaka Python, solusinya sering kali kurang optimal, karena kemungkinan tidak berguna di sistem operasi lain dengan API yang berbeda.
erikbwork
4

Dengan pustaka subproses yang lebih baru, Anda sekarang dapat menggunakan kode berikut (solusi khusus * 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
Berniey
sumber
Terima kasih atas jawabannya. BTW, Anda tidak boleh menggunakan str.split () pada baris cmd. gunakan shlex.split (cmd) insteed.
emnoor
Daripada menggunakan shlex.split, mengapa tidak dijalankan saja subprocess.check_output(['file', '--mime-type', filename])?
Flimm
1

Anda juga dapat menggunakan kode ini (python murni dengan 3 byte file header):

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"

tanpa penginstalan paket apa pun [dan perbarui versi]

hijau sepanjang tahun
sumber
Bagaimana cara memeriksa xlsx?
Harsha Biyani
Anda dapat menggunakan 4 atau 8 byte. XLSX (MS Office Open XML Format Document) => 50 4B 03 04 (4 Bytes) => ASCII (PK ••) atau XLSX (dokumen MS Office 2007) => 50 4B 03 04 14 00 06 00 (8 Bytes) = > ASCII (PK ••••••)
evergreen
0

Hanya bekerja untuk Linux tetapi Menggunakan modul python "sh" Anda cukup memanggil perintah shell

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

pip instal sh

impor sh

sh.file ("/ root / file")

Keluaran: / root / file: teks ASCII

Lelouch
sumber