Include Exclude Patterns

This document serves as a practical reference guide for understanding how include-exclude pattern matching works, which uses the same pattern syntax as .gitignore files. Through a series of examples, you’ll learn exactly how different patterns match file paths in various directory structures. Whether you need to include specific file types, exclude certain directories, or create complex matching rules, these examples will help you identify the correct pattern syntax for your specific needs. Use this guide as a quick reference when implementing file filtering in your projects to ensure your patterns behave as expected.

[1]:
import pathspec

def test_pattern(
    pattern: str,
    path: str,
):
    print(f"pattern       = {pattern}")
    print(f"path          = {path}")
    p = pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, [pattern])
    is_match_flag = p.match_file(path)
    print(f"{is_match_flag = }")

Pattern: README.md

Matches any file named README.md in any directory or subdirectory.

[2]:
test_pattern(pattern="README.md", path="README.md")
pattern       = README.md
path          = README.md
is_match_flag = True
[3]:
test_pattern(pattern="README.md", path="folder/README.md")
pattern       = README.md
path          = folder/README.md
is_match_flag = True
[4]:
test_pattern(pattern="README.md", path="folder/subfolder/README.md")
pattern       = README.md
path          = folder/subfolder/README.md
is_match_flag = True

Pattern: *.py

Matches any Python file (.py extension) in any directory or subdirectory.

[5]:
test_pattern(pattern="*.py", path="example.py")
pattern       = *.py
path          = example.py
is_match_flag = True
[6]:
test_pattern(pattern="*.py", path="folder/example.py")
pattern       = *.py
path          = folder/example.py
is_match_flag = True
[7]:
test_pattern(pattern="*.py", path="folder/subfolder/example.py")
pattern       = *.py
path          = folder/subfolder/example.py
is_match_flag = True

Pattern: src/*.py

Matches Python files directly in the src directory, but not in subdirectories of src.

[8]:
test_pattern(pattern="src/*.py", path="example.py")
pattern       = src/*.py
path          = example.py
is_match_flag = False
[9]:
test_pattern(pattern="src/*.py", path="folder/example.py")
pattern       = src/*.py
path          = folder/example.py
is_match_flag = False
[10]:
test_pattern(pattern="src/*.py", path="src/example.py")
pattern       = src/*.py
path          = src/example.py
is_match_flag = True
[11]:
test_pattern(pattern="src/*.py", path="src/folder/example.py")
pattern       = src/*.py
path          = src/folder/example.py
is_match_flag = False

Pattern: src/**/*.py

Matches Python files in the src directory and all of its subdirectories at any depth.

[12]:
test_pattern(pattern="src/**/*.py", path="src/example.py")
pattern       = src/**/*.py
path          = src/example.py
is_match_flag = True
[13]:
test_pattern(pattern="src/**/*.py", path="src/folder/example.py")
pattern       = src/**/*.py
path          = src/folder/example.py
is_match_flag = True
[14]:
test_pattern(pattern="src/**/*.py", path="src/folder/subfolder/example.py")
pattern       = src/**/*.py
path          = src/folder/subfolder/example.py
is_match_flag = True

Pattern: tmp

Matches any path that contains “tmp”, including files in tmp directory or any directory named tmp.

[15]:
test_pattern(pattern="tmp", path="tmp/file.txt")
pattern       = tmp
path          = tmp/file.txt
is_match_flag = True
[16]:
test_pattern(pattern="tmp", path="tmp/folder/file.txt")
pattern       = tmp
path          = tmp/folder/file.txt
is_match_flag = True
[17]:
test_pattern(pattern="tmp", path="tmp/folder/subfolder/file.txt")
pattern       = tmp
path          = tmp/folder/subfolder/file.txt
is_match_flag = True
[18]:
test_pattern(pattern="tmp", path="tests/tmp/file.txt")
pattern       = tmp
path          = tests/tmp/file.txt
is_match_flag = True
[19]:
test_pattern(pattern="tmp", path="tests/tmp/folder/file.txt")
pattern       = tmp
path          = tests/tmp/folder/file.txt
is_match_flag = True
[20]:
test_pattern(pattern="tmp", path="tests/tmp/subfolder/file.txt")
pattern       = tmp
path          = tests/tmp/subfolder/file.txt
is_match_flag = True

Pattern: tmp/

Matches contents inside tmp directories, but not the tmp directory itself.

[21]:
test_pattern(pattern="tmp/", path="tmp")
pattern       = tmp/
path          = tmp
is_match_flag = False
[22]:
test_pattern(pattern="tmp/", path="tmp/file.txt")
pattern       = tmp/
path          = tmp/file.txt
is_match_flag = True
[23]:
test_pattern(pattern="tmp/", path="tmp/folder/file.txt")
pattern       = tmp/
path          = tmp/folder/file.txt
is_match_flag = True
[24]:
test_pattern(pattern="tmp/", path="tmp/folder/subfolder/file.txt")
pattern       = tmp/
path          = tmp/folder/subfolder/file.txt
is_match_flag = True
[25]:
test_pattern(pattern="tmp/", path="tests/tmp/file.txt")
pattern       = tmp/
path          = tests/tmp/file.txt
is_match_flag = True
[26]:
test_pattern(pattern="tmp/", path="tests/tmp/folder/file.txt")
pattern       = tmp/
path          = tests/tmp/folder/file.txt
is_match_flag = True
[27]:
test_pattern(pattern="tmp/", path="tests/tmp/subfolder/file.txt")
pattern       = tmp/
path          = tests/tmp/subfolder/file.txt
is_match_flag = True

Pattern: docs/source/*/**/index.rst

Matches index.rst files that are at least 2 levels deep in the directory structure under docs/source, but not directly in docs/source.

[28]:
test_pattern(pattern="docs/source/*/**/index.rst", path="docs/source/index.rst")
pattern       = docs/source/*/**/index.rst
path          = docs/source/index.rst
is_match_flag = False
[29]:
test_pattern(pattern="docs/source/*/**/index.rst", path="docs/source/Section-1/index.rst")
pattern       = docs/source/*/**/index.rst
path          = docs/source/Section-1/index.rst
is_match_flag = True
[30]:
test_pattern(pattern="docs/source/*/**/index.rst", path="docs/source/Section-1/Section-1-1/index.rst")
pattern       = docs/source/*/**/index.rst
path          = docs/source/Section-1/Section-1-1/index.rst
is_match_flag = True

Pattern: *.py[cod]

Matches Python compiled files (.pyc, .pyo, .pyd), useful for excluding compiled Python code.

[31]:
test_pattern(pattern="*.py[cod]", path="test.pyc")
pattern       = *.py[cod]
path          = test.pyc
is_match_flag = True
[32]:
test_pattern(pattern="*.py[cod]", path="test.pyo")
pattern       = *.py[cod]
path          = test.pyo
is_match_flag = True
[33]:
test_pattern(pattern="*.py[cod]", path="test.pyd")
pattern       = *.py[cod]
path          = test.pyd
is_match_flag = True