ปกติเวลาค้นชื่อไฟล์ในเชลยูนิกซ์จะนิยมเขียนแสดงในรูปแบบกล็อบ ดังที่ได้เขียนถึงไว้แล้วในบทความที่แล้ว
https://phyblas.hinaboshi.com/20190109 ส่วนในภาษาไพธอนเองถ้าต้องการค้นชื่อไฟล์ด้วยกล็อบก็มีมอดูลชื่อ glob สามารถใช้งานได้สะดวก
ในบทความนี้จะแนะนำวิธีการใช้กล็อบในไพธอน ส่วนรายละเอียดวิธีการเขียนกล็อบสามารถเข้าไปอ่านในบทความที่แล้ว
glob.glob ฟังก์ชัน glob.glob (ชื่อฟังก์ชันเหมือนกับชื่อมอดูล ระวังสับสน) เป็นคำสั่งพื้นฐานที่ใช้งานบ่อยสุดใน glob การใช้งานง่ายๆตรงไปตรงมาเลยคือ
ตัวอย่างการใช้ สมมุติว่าในโฟลเดอร์ที่อยู่มีไฟล์ชื่อ a.txt bb.txt ccc.txt dddd.csv
from glob import glob
print(glob('*.txt')) # ได้ ['ccc.txt', 'bb.txt', 'a.txt']
ผลที่ได้จะเป็นลิสต์ของชื่อไฟล์ทั้งหมดที่เข้าข่าย เพียงแต่ว่าผลที่ได้มักจะไม่ได้เรียงกันตามลำดับ อะไรจะขึ้นก่อนนั้นไม่อาจรู้ได้ หากต้องการให้เรียงตามชื่อควรใช้ sorted ช่วยจะดีกว่า
print(sorted(glob('*.txt'))) # ได้ ['a.txt', 'bb.txt', 'ccc.txt']
นอกจากนี้ถ้าต้องการให้เรียงตามขนาดไฟล์หรือเรียงตามเวลาที่แก้ไขไฟล์ก็อาจใช้แบบนี้ได้
import os
sorted(glob('*.txt'),key=os.path.getsize) # เรียงตามขนาดไฟล์
sorted(glob('*.txt'),key=os.path.getmtime) # เรียงตามเวลาที่แก้ไขไฟล์
glob.iglob คำสั่ง glob.glob จะคืนค่าเป็นลิสต์ ซึ่งรายชื่อไฟล์ทั้งหมดจะถูกนำมาแสดงหรือเก็บไว้ในตัวแปรโดยทันที
แต่ในกรณีที่ต้องการนำมาวนด้วย for เพื่อเอาชื่อไฟล์มาใช้งานทีละชื่ออาจเลือกใช้คำสั่ง glob.iglob ได้
glob.iglob เหมือนกับ glob.glob แต่ต่างกันตรงที่ผลการค้นหาที่ได้จะเป็นเจเนอเรเตอร์ที่จะให้ค่าชื่อไฟล์ออกมาเมื่อถูกเรียกใช้ ไม่ได้ให้เป็นลิสต์ทันที
from glob import iglob
print(iglob('*.txt')) # ได้
ตัวอย่างการใช้ เช่นเอามาเข้าใน for เพื่อทำอะไรกับไฟล์ทีละไฟล์ได้ เช่นถ้าจะค้นหาไฟล์ทุกไฟล์เพื่อมาเปิดแล้วแสดงเนื้อหาทั้งหมดก็ทำแบบนี้ได้ เป็นต้น
for g in sorted(iglob('*.txt')):
f = open(g)
print(f.read())
f.close()
glob.iglob จะไปค้นหาไฟล์ตอนที่มันถูกเรียกใช้ใน for นั่นหมายความว่าต่อให้ใช้ glob.iglob เพื่อสร้างตัวเจเนอเรเตอร์ไว้ก่อน ถ้าระหว่างนั้นไฟล์ในนั้นมีการเปลี่ยนแปลง ผลที่ได้ออกมาก็จะเป็นไปตามหลังจากการเปลี่ยนแปลง
อีกอย่างคือเนื่องจาก glob.iglob เป็นเจเนอเรเตอร์จึงถูกใช้วนใน for ได้แค่ครั้งเดียว นำมาใช้ซ้ำไม่ได้ถ้าไม่สร้างใหม่
รายละเอียดเพิ่มเติมเกี่ยวกับเจเนอเรเตอร์ อ่านได้ใน
https://phyblas.hinaboshi.com/tsuchinoko26 glob.glob1 ฟังก์ชัน glob.glob1 จะคล้ายกับ glob.glob แต่ต่างกันตรงที่จะแยกโฟลเดอร์หลักกับไฟล์ที่ต้องการค้นออกจากกัน
เช่น ๒
from glob import glob,glob1
glob1('fg/','*') # ได้ ['ac.txt', 'ba.txt']
ถ้าใช้ glob จะเขียนแบบนี้
glob('fg/*') # ได้ ['fg/ac.txt', 'fg/ba.txt']
ผลที่ได้จะค้นเจอไฟล์เดียวกัน แต่ใช้ glob1 แล้วจะไม่มีชื่อโฟลเดอร์ติดมาด้วย ดังนั้นอาจสะดวกกว่าถ้าต้องการแค่ชื่อไฟล์อย่างเดียว
ถ้าเข้าใจความแตกต่างระหว่าง glob, iglob และ glob1 ก็สามารถแยกใช้ตามความเหมาะสมได้
fnmatch.fnmatch หรือ
glob.fnmatch.fnmatch ฟังก์ชัน fnmatch.fnmatch ในมอดูล fnmatch (ชื่อฟังก์ชันเหมือนกับชื่อมอดูลอีกแล้ว) ใช้สำหรับแค่ดูว่าชื่อไฟล์เข้าข่ายตามรูปแบบกล็อบที่กำหนดหรือไม่
ตัวอย่างการใช้
from fnmatch import fnmatch
print(fnmatch('a.py','*.py')) # ได้ True
print(fnmatch('a.py','*.txt')) # ได้ False
ที่จริงแล้วคำสั่ง glob ในไพธอนคือการเรียก os.listdir ซึ่งเป็นคำสั่งสำหรับไล่รายชื่อไฟล์ทั้งหมดในโฟลเดอร์ แล้วจากนั้นก็นำชื่อไฟล์มาคัดกรองด้วย fnmatch อีกทีนั่นเอง
ดังนั้น glob('*.txt') จะเท่ากับ
[g for g in os.listdir('./') if (fnmatch(g,'*.txt'))]
มอดูล fnmatch นี้มีการเรียกใช้โดย glob จึงถูกทำให้สามารถเข้าถึงผ่านมอดูล glob ได้ด้วย นั่นคือ fnmatch เท่ากับ glob.fnmatch
import glob,fnmatch
print(glob.fnmatch is fnmatch) # ได้ True
อ้างอิง