ماژول fnmatch در کتابخانه استاندارد پایتون برای مقایسه نام فایلها با الگوهای سبک یونیکس (Unix shell-style wildcards) استفاده میشود. این ماژول بر خلاف re (Regular Expressions) سادهتر است و دقیقاً همان منطقی را پیادهسازی میکند که هنگام جستجوی فایلها در ترمینال یا CMD با کاراکترهایی مثل * و ? استفاده میکنید.
در این مقاله، از مفاهیم اولیه تا پیادهسازیهای حرفهای و تبدیل این الگوها به Regex را بررسی میکنیم.

سطح مقدماتی (Beginner Level)
در سطح مقدماتی یاد میگیریم که چگونه رشتهها را با الگوهای ساده مقایسه کنیم و تفاوت رفتار سیستمعاملهای مختلف را درک کنیم.
۱. کاراکترهای جایگزین (Wildcards)
در fnmatch از کاراکترهای خاصی برای تطبیق استفاده میشود:
*: تطبیق با هر تعداد کاراکتر (حتی صفر).?: تطبیق دقیقاً با یک کاراکتر.[seq]: تطبیق با یکی از کاراکترهای داخل براکت (مثل[a-z]).[!seq]: تطبیق با هر کاراکتری که در براکت نیست.
مثال ۱: استفاده از * (ستاره)
این کد بررسی میکند که آیا نام فایل با پسوند .txt ختم میشود یا خیر.
مثال ۲: استفاده از ? و []
در این مثال میخواهیم نام فایلهایی را پیدا کنیم که دقیقاً الگوی log_ و سپس یک عدد تکرقمی دارند.
۲. حساسیت به بزرگی و کوچکی حروف (Case Sensitivity)
رفتار تابع fnmatch() بستگی به سیستمعامل شما دارد:
- در ویندوز: حروف بزرگ و کوچک یکسان در نظر گرفته میشوند (Case-insensitive).
- در لینوکس/مک: حروف بزرگ و کوچک متفاوت هستند (Case-sensitive).
اگر میخواهید کد شما در تمام سیستمعاملها رفتار یکسانی داشته باشد (یعنی همیشه حساس به حروف باشد)، باید از fnmatchcase() استفاده کنید.
مثال ۱: تفاوت رفتار (Concept)
این کد فقط یک نمایش است و خروجی آن به سیستمعامل شما بستگی دارد.
# Static Example
import fnmatch
import os
# اگر در ویندوز باشید True و اگر در لینوکس باشید False برمیگرداند
print(fnmatch.fnmatch('image.JPG', '*.jpg'))
مثال ۲: اجبار به حساسیت حروف با fnmatchcase
این تابع فارغ از سیستمعامل، همیشه حروف بزرگ و کوچک را متمایز میداند.
سطح پیشرفته (Professional Level)
در بخش حرفهای، به سراغ فیلتر کردن لیستهای بزرگ، بهینهسازی و درک ارتباط fnmatch با عبارات باقاعده (Regex) میرویم.
۱. فیلتر کردن لیستها با filter()
به جای اینکه در یک حلقه for تکتک آیتمها را با fnmatch چک کنید، میتوانید از تابع بهینهشدهی filter() استفاده کنید. این تابع یک لیست از نامها را گرفته و زیرمجموعهای که با الگو مطابقت دارد را برمیگرداند.
مثال ۱: استخراج فایلهای تصویری
فرض کنید لیستی از فایلها دارید و فقط پسوندهای خاصی را میخواهید.
مثال ۲: مقایسه عملکرد (Best Practice)
استفاده از fnmatch.filter معمولاً خواناتر و سریعتر از نوشتن List Comprehension به صورت دستی است.
# روش معمولی (کد استاتیک)
results = [f for f in all_files if fnmatch.fnmatch(f, "*.py")]
# روش حرفهای (پیشنهاد شده)
results = fnmatch.filter(all_files, "*.py")
۲. تبدیل الگوهای fnmatch به Regex با translate()
تابع fnmatch در پشت صحنه الگوهای شما را به عبارات باقاعده (Regex) تبدیل میکند تا ماژول re بتواند آنها را پردازش کند. با استفاده از تابع translate() میتوانید ببینید که الگوی سادهی شما به چه الگوی پیچیدهای تبدیل میشود. این برای دیباگ کردن یا استفاده از الگوهای فایلی در توابع Regex بسیار مفید است.
مثال ۱: مشاهده ترجمه الگو
مثال ۲: استفاده ترکیبی با ماژول re
شما میتوانید یک الگوی ساده fnmatch بسازید، آن را ترجمه کنید و سپس با قدرت ماژول re جستجوهای پیشرفتهتری انجام دهید (مثلاً re.IGNORECASE).
۳. نکات کلیدی و تفاوت با glob
یک اشتباه رایج بین برنامهنویسان پایتون، اشتباه گرفتن fnmatch با glob است.
fnmatch: فقط عملیات رشتهای انجام میدهد. یعنی بررسی نمیکند که آیا فایل واقعاً در دیسک وجود دارد یا نه. صرفاً میگوید "آیا این رشته متنی با آن الگو همخوانی دارد؟".glob: به سیستم فایل (File System) متصل میشود و لیست فایلهای واقعی موجود در دایرکتوری را برمیگرداند.
مثال: شبیهسازی رفتار glob با os.listdir و fnmatch
اگر بخواهید فایلهای واقعی را بدون استفاده از ماژول glob پیدا کنید، باید اینگونه عمل کنید: