PurePath.match

match('*.py') is true for any path whose LAST component ends in .py — a relative pattern is matched from the right. full_match('**/*.py') matches the entire path, with ** spanning any number of folders, exactly like Path.glob.

pathlib methodPython 3.4+ (full_match 3.13+)Live demo
Common call
p.full_match('src/**/*.py')
Returns
True / False
Replaces
fnmatch.fnmatch(str(p), pattern)
Watch out
in match(), ** is just * — use full_match for recursive patterns
PurePath.match(patternpattern — Glob pattern: * ? [seq] [!seq] within one component; ** (full_match only) for any number of components.type: str | PurePath · required, *, case_sensitivecase_sensitive — None follows the flavour: case-sensitive for POSIX, insensitive for Windows.type: bool | None · default: None=None) / .full_match(pattern, *, case_sensitivecase_sensitive — None follows the flavour: case-sensitive for POSIX, insensitive for Windows.type: bool | None · default: None=None)
→ bool

Demo

Live evaluation
The same pattern through both methods.
Try:
Inputs
pathstra path
patternstra glob pattern
Code
from pathlib import PurePosixPath
p = PurePosixPath('src/pkg/core.py')
(p.match('*.py'), p.full_match('*.py'))
Result
(True, False)

For 'src/pkg/core.py' the relative pattern '*.py' matches through match() (only the last part is compared) but not through full_match(), which needs the whole path. '**/*.py' works in both, but for different reasons: full_match treats ** as any number of folders, while match treats ** like * and still compares from the right. An empty pattern is a ValueError for match(), and the demo never gets to full_match(); on its own, full_match('') only matches the empty path '.'.

Parameters

NameTypeRequiredDescription
patternstr | PurePathyesGlob pattern: * ? [seq] [!seq] within one component; ** (full_match only) for any number of components.
case_sensitivebool | Noneno (None)None follows the flavour: case-sensitive for POSIX, insensitive for Windows.

Return value

bool — Whether the path matches the pattern.

Common patterns

Filter a list of paths
full_match with ** mirrors what glob would select.
from pathlib import PurePosixPath
sources = [p for p in paths if PurePosixPath(p).full_match('src/**/*.py')]
Case-insensitive extension test
Force case-insensitivity on POSIX paths.
from pathlib import Path
images = [p for p in Path('photos').iterdir() if p.match('*.jp*g', case_sensitive=False)]
Ignore rules
Skip paths that match any pattern.
from pathlib import PurePosixPath
IGNORE = ['**/__pycache__/**', '**/*.pyc', '.git/**']
def ignored(p):
    return any(PurePosixPath(p).full_match(pat) for pat in IGNORE)

Examples

1. match compares from the right
from pathlib import PurePosixPath PurePosixPath('a/b/c.py').match('b/*.py')
Returns
True
2. full_match needs the whole path
from pathlib import PurePosixPath PurePosixPath('a/b/c.py').full_match('b/*.py')
Returns
False
3. ** spans folders in full_match
from pathlib import PurePosixPath PurePosixPath('a/b/c.py').full_match('**/*.py')
Returns
True
4. ** can also match zero folders
from pathlib import PurePosixPath PurePosixPath('c.py').full_match('**/*.py')
Returns
True
5. An absolute pattern must match everything
from pathlib import PurePosixPath PurePosixPath('/a/b.py').match('/*.py')
Returns
False
6. case_sensitive=False
from pathlib import PurePosixPath PurePosixPath('IMG_01.JPG').match('*.jpg', case_sensitive=False)
Returns
True
7. Empty pattern
from pathlib import PurePosixPath PurePosixPath('a.txt').match('')
Returns
ValueError: empty pattern

Pitfalls

1. Expecting match("*.py") to mean "a .py file in this folder"
match() only looks at as many trailing components as the pattern has, so any depth matches. Use full_match for anchored patterns.
match
from pathlib import PurePosixPath
PurePosixPath('vendor/lib/x.py').match('*.py')
True
full_match
from pathlib import PurePosixPath
PurePosixPath('vendor/lib/x.py').full_match('*.py')
False
2. Case differences on POSIX
PurePosixPath and PosixPath match case-sensitively by default; Windows paths do not.
default
from pathlib import PurePosixPath
PurePosixPath('README.MD').full_match('*.md')
False
case_sensitive=False
from pathlib import PurePosixPath
PurePosixPath('README.MD').full_match('*.md', case_sensitive=False)
True

When to use

Use it
  • Filtering paths you already have (from a list, a zip, a database)
  • Ignore / include rules with ** (full_match)
Reach for something else
  • Finding files on disk → Path.glob / rglob
  • Regular-expression power → re.fullmatch on as_posix()

Notes

CPython impl
Both are defined on PurePathBase in Lib/pathlib/_abc.py; patterns are compiled with glob.translate(…, include_hidden=True), so * also matches names starting with a dot
Version
full_match added in 3.13; case_sensitive parameter added to match in 3.12
Semantics
Same pattern language as Path.glob: * ? [seq] [!seq] inside one component, ** for any number of components (full_match only)

FAQ

match() compares a relative pattern against the end of the path and treats ** like *. full_match() (3.13+) compares against the whole path and treats ** as any number of folders, the same as glob().