thelinuxvault blog

fnmatch - Unix Filename Pattern Matching in Python

In Python, the fnmatch module provides a useful way to perform Unix-style filename pattern matching. When working with files, you often need to find files that match a certain naming scheme. Instead of writing complex regular expressions or looping through file lists with custom string comparisons, fnmatch allows you to use simple and familiar Unix glob patterns to achieve this.

This blog will provide a detailed overview of the fnmatch module, including basic concepts, available functions, common and best practices, and example usage.

2026-06

Table of Contents#

  1. Understanding Unix Glob Patterns
  2. The fnmatch Module Functions
  3. Common Practices and Best Practices
  4. Example Usage
  5. Reference

Understanding Unix Glob Patterns#

Unix glob patterns are a set of rules for matching filenames in a shell. Here are some common glob patterns:

  • *: Matches any sequence of zero or more characters. For example, *.txt matches all files with the .txt extension.
  • ?: Matches any single character. For example, file?.txt matches file1.txt, file2.txt, etc.
  • [ ]: Matches any single character within the brackets. For example, [abc].txt matches a.txt, b.txt, and c.txt.
  • [! ]: Matches any single character not within the brackets. For example, [!abc].txt matches any .txt file whose first character is not a, b, or c.

The fnmatch Module Functions#

fnmatch.fnmatch()#

The fnmatch.fnmatch(filename, pattern) function checks if the given filename matches the given pattern. It returns True if the match is successful and False otherwise. The comparison is case-insensitive on systems where the file system is case-insensitive.

import fnmatch
 
filename = 'data.txt'
pattern = '*.txt'
result = fnmatch.fnmatch(filename, pattern)
print(result)  # Output: True

fnmatch.fnmatchcase()#

The fnmatch.fnmatchcase(filename, pattern) function is similar to fnmatch(), but it performs a case-sensitive comparison.

import fnmatch
 
filename = 'Data.txt'
pattern = '*.txt'
result = fnmatch.fnmatchcase(filename, pattern)
print(result)  # Output: False if you are looking for all - lowercase matches

fnmatch.filter()#

The fnmatch.filter(names, pattern) function takes a list of names (usually filenames) and a pattern. It returns a new list containing only the names that match the pattern.

import fnmatch
 
file_list = ['file1.txt', 'file2.csv', 'image.jpg']
pattern = '*.txt'
matching_files = fnmatch.filter(file_list, pattern)
print(matching_files)  # Output: ['file1.txt']

fnmatch.translate()#

The fnmatch.translate(pattern) function translates a Unix glob pattern into a regular expression pattern. This can be useful if you want to use the power of regular expressions with a glob - style pattern.

import fnmatch
 
pattern = '*.txt'
regex_pattern = fnmatch.translate(pattern)
print(regex_pattern)  # Output: '(?s:.*\\.txt)\\Z'

Common Practices and Best Practices#

  • Use fnmatch for Simple Matching: If you only need simple filename matching based on Unix glob patterns, fnmatch is a great choice. It is easier to read and write compared to regular expressions.
  • Case Sensitivity: Be aware of the case sensitivity of your file system and use fnmatchcase() when you need a case - sensitive match.
  • Combining with os Module: You can combine fnmatch with the os module to find files in a directory that match a certain pattern. For example:
import fnmatch
import os
 
pattern = '*.py'
file_list = []
for root, dirs, files in os.walk('.'):
    for name in files:
        if fnmatch.fnmatch(name, pattern):
            file_list.append(os.path.join(root, name))
print(file_list)
  • Error Handling: Although fnmatch functions rarely raise exceptions, it's still a good practice to handle potential errors in your code, especially when working with file systems.

Example Usage#

Let's say you have a directory with a lot of files, and you want to find all Python and Markdown files.

import fnmatch
import os
 
python_pattern = '*.py'
markdown_pattern = '*.md'
python_files = []
markdown_files = []
 
for root, dirs, files in os.walk('.'):
    for name in files:
        if fnmatch.fnmatch(name, python_pattern):
            python_files.append(os.path.join(root, name))
        elif fnmatch.fnmatch(name, markdown_pattern):
            markdown_files.append(os.path.join(root, name))
 
print("Python files:", python_files)
print("Markdown files:", markdown_files)

Reference#