จะตรวจสอบประเภทไฟล์ที่ไม่มีนามสกุลใน python ได้อย่างไร?


87

ฉันมีโฟลเดอร์ที่เต็มไปด้วยไฟล์และไม่มีนามสกุล ฉันจะตรวจสอบประเภทไฟล์ได้อย่างไร? ฉันต้องการตรวจสอบประเภทไฟล์และเปลี่ยนชื่อไฟล์ตามนั้น สมมติว่าฟังก์ชันfiletype(x)ส่งคืนประเภทไฟล์เช่นpng. ฉันต้องการทำสิ่งนี้:

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

ฉันต้องทำอย่างไร



file typesคุณจะต้องระบุข้อมูลเพิ่มเติมเกี่ยวกับการมี คุณหมายถึงการพิจารณาว่าเป็น gif, png, bmp หรือ jpg หรือไม่? คุณแค่อยากรู้ว่ามันเป็นข้อความ / ไบนารีหรือไม่? ปฏิบัติการได้?
JoeFish

@ thg435 เมื่อคุณมีประเภท MIME แล้วมีวิธีการแปลงเป็นนามสกุลไฟล์ที่เหมาะสมหรือไม่?
Mark Ransom

@Mark: ใช่ใช้guess_extensionแต่จริงๆแล้ว mimetypes จะไม่ทำงานที่นี่เพราะมันขึ้นอยู่กับนามสกุลไฟล์ สิ่งที่พวกเขาต้องการคือ libmagic (ดูคำตอบที่ 2 ในลิงค์)
georg

1
ลองใช้pypi.org/project/filetypeนี้ไหม
zx1986

คำตอบ:


92

มีไลบรารี Python ที่สามารถจดจำไฟล์ตามเนื้อหา (โดยปกติจะเป็นส่วนหัว / หมายเลขเมจิก) และไม่ต้องอาศัยชื่อไฟล์หรือนามสกุล

python-magicหากคุณกำลังอยู่หลายชนิดแฟ้มที่แตกต่างกันคุณสามารถใช้ นั่นเป็นเพียงการผูก Python สำหรับmagicไลบรารีที่มีชื่อเสียง สิ่งนี้มีชื่อเสียงที่ดีและ (การรับรองเล็ก ๆ น้อย ๆ ) ในการใช้งานที่ จำกัด ที่ฉันได้ทำมามันเป็นของแข็ง

นอกจากนี้ยังมีไลบรารีสำหรับไฟล์ประเภทพิเศษเพิ่มเติม ตัวอย่างเช่นไลบรารีมาตรฐาน Python มีimghdrโมดูลที่ทำสิ่งเดียวกันกับประเภทไฟล์รูปภาพเท่านั้น

หากคุณจำเป็นต้องตรวจสอบประเภทของไฟล์พึ่งพาฟรี (หลามบริสุทธิ์) filetypeดู


2
แพคเกจใช้python-magic-win64งานได้สำหรับฉันใน Windows
ChesuCR

2
imghdrกับการรวมกันของประเภทไฟล์ทำงานให้ฉันใน windows
Hrushikesh Dhumal

62

หลามเมจิกห้องสมุดให้ฟังก์ชันการทำงานที่คุณต้องการ

คุณสามารถติดตั้งไลบรารี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 ที่อยู่ใต้ฝากระโปรงซึ่งเป็นไลบรารีเดียวกับที่ใช้โดยfileคำสั่ง* NIX ดังนั้นสิ่งนี้จะเหมือนกับคำตอบของกระบวนการย่อย / เชลล์ แต่ไม่มีค่าโสหุ้ยนั้น


6
ระวังว่าแพ็คเกจ debian / ubuntu ที่เรียกว่า python-magic นั้นแตกต่างจากแพ็คเกจ pip ที่มีชื่อเดียวกัน ทั้งสองมีimport magicแต่เนื้อหาที่เข้ากันไม่ได้ ดูstackoverflow.com/a/16203777/3189สำหรับข้อมูลเพิ่มเติม
Hamish Downer

1
@ ริชาร์ดคุณสนใจที่จะอธิบายรายละเอียดเกี่ยวกับค่าใช้จ่ายหรือไม่? อะไรทำให้python-magicไลบรารีมีประสิทธิภาพมากขึ้นจากการใช้แนวทางกระบวนการย่อย
Greg

9

บน unix และ linux มีfileคำสั่งให้เดาประเภทไฟล์ มีแม้กระทั่งเป็นพอร์ตหน้าต่าง

จากหน้าคน :

ไฟล์ทดสอบแต่ละอาร์กิวเมนต์เพื่อพยายามจัดประเภท มีการทดสอบสามชุดตามลำดับดังนี้การทดสอบระบบไฟล์การทดสอบเลขวิเศษและการทดสอบภาษา การทดสอบครั้งแรกที่ประสบความสำเร็จทำให้ประเภทไฟล์ถูกพิมพ์

คุณจะต้องเรียกใช้fileคำสั่งด้วยไฟล์subprocessโมดูลจากนั้นแยกวิเคราะห์ผลลัพธ์เพื่อหาส่วนขยาย

แก้ไข: ไม่สนใจคำตอบของฉัน ใช้คำตอบของ Chris Johnson แทน


+1 ฉันไม่รู้เลยว่าfileทำมากขนาดนั้น # file arc.gif arc.gif: GIF image data, version 89a, 234 x 269
JoeFish

ฉันหวังว่าจะมีคนตอบที่ดีกว่านี้ ยังมีงานอีกมากสำหรับ OP ไม่ใช่การเรียกใช้ฟังก์ชันธรรมดา
Steven Rumbalski

2
+1 ข้อดีอย่างหนึ่งของการใช้fileคำสั่งคือเป็นแบบเนทีฟบนลินุกซ์ดิสทริบิวชัน (ส่วนใหญ่?) ในขณะที่python-magicไม่ได้และต้องดาวน์โหลดและติดตั้งก่อนจึงจะสามารถใช้งานได้ นี่เป็นปัญหาเล็กน้อยหากสคริปต์ที่ใช้โมดูลควรเป็นแบบพกพา
HelloGoodbye


6

คุณยังสามารถติดตั้งการfileผูกอย่างเป็นทางการสำหรับ Python ซึ่งเป็นไลบรารีที่เรียกว่าfile-magic(ไม่ใช้ ctypes เช่นpython-magic)

มันมีอยู่ใน PyPI เป็นไฟล์มายากลและใน Debian เป็นหลามมายากล สำหรับฉันไลบรารีนี้เป็นไลบรารีที่ดีที่สุดในการใช้งานเนื่องจากมีให้บริการใน PyPI และบน Debian (และอาจเป็นการกระจายอื่น ๆ ) ทำให้กระบวนการปรับใช้ซอฟต์แวร์ของคุณง่ายขึ้น ฉันเขียนบล็อกเกี่ยวกับวิธีการใช้งานแล้วด้วย


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

ดังที่สตีเวนชี้ให้เห็นsubprocessคือหนทาง คุณสามารถรับเอาต์พุตคำสั่งได้ตามวิธีด้านบนตามที่โพสต์นี้กล่าว


และคุณจับเอาท์พุทได้อย่างไร?
Mark Ransom

@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

ขอบคุณสำหรับคำตอบ. BTW คุณไม่ควรใช้ str.split () ในบรรทัด cmd ใช้ shlex.split (cmd) insteed
emnoor

แทนที่จะใช้shlex.splitทำไมไม่เพียงแค่เรียกใช้subprocess.check_output(['file', '--mime-type', filename])?
Flimm

1

คุณยังสามารถใช้รหัสนี้ (python บริสุทธิ์โดยไฟล์ส่วนหัว 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 ได้อย่างไร?
Harsha Biyani

คุณสามารถใช้ได้ 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 ติดตั้ง sh

นำเข้า sh

sh.file ("/ ราก / ไฟล์")

เอาต์พุต: / root / file: ข้อความ ASCII

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.