Glob-style path matcher with negation and brace expansion. Zero dependencies.
pip install pathmaskOr from source:
git clone https://github.com/nripankadas07/pathmask.git
cd pathmask
pip install -e .from pathmask import match, filter_paths
# Simple matching
match("src/main.js", "src/*.js") # True
match("src/utils/helper.js", "src/*.js") # False
# Recursive matching
match("src/utils/helper.js", "src/**/*.js") # True
# Filter paths
paths = ["a.txt", "b.md", "c.txt"]
filter_paths(paths, "*.txt") # ["a.txt", "c.txt"]
# Negation
filter_paths(paths, "!*.md") # ["a.txt", "c.txt"]*� Matches any characters except/**� Matches any characters including/(recursive)?� Matches any single character except/[abc]� Character class[!abc]� Negated character class{a,b,c}� Brace expansion!pattern� Negation (returns non-matching paths)
from pathmask import match
# Literal matching
match("file.txt", "file.txt") # True
# Single character
match("file.txt", "file?.txt") # False
match("file1.txt", "file?.txt") # True
# Wildcard
match("main.js", "*.js") # True
match("src/main.js", "*.js") # False (doesn't cross /)# ** matches across directory boundaries
match("src/utils/helper.js", "src/**/*.js") # True
match("a/b/c/d/file.txt", "a/**/file.txt") # True
match("file.txt", "**/*.txt") # Truematch("file1.txt", "file[0-9].txt") # True
match("fileA.txt", "file[0-9].txt") # False
match("fileA.txt", "file[!0-9].txt") # Truematch("style.css", "*.{js,css,html}") # True
match("main.js", "*.{js,css,html}") # True
match("app.py", "*.{js,css,html}") # False
# Nested braces
match("a", "{a,{b,c}}") # True
match("c", "{a,{b,c}}") # Truefrom pathmask import filter_paths
paths = [
"src/main.js",
"src/utils/helper.js",
"test/spec.js",
"README.md"
]
# Match all JS files
filter_paths(paths, "**/*.js")
# ["src/main.js", "src/utils/helper.js", "test/spec.js"]
# Exclude markdown files
filter_paths(paths, "!*.md")
# ["src/main.js", "src/utils/helper.js", "test/spec.js"]For repeated use, compile patterns for better performance:
from pathmask import compile_pattern
pattern = compile_pattern("src/**/*.{js,ts}")
pattern.match("src/main.js") # True
pattern.match("src/utils/helper.ts") # True
pattern.match("test/spec.js") # FalseTest if a path matches a glob pattern.
Parameters:
path(str): File path to matchpattern(str): Glob pattern
Returns:
- bool: True if path matches pattern
Raises:
PathmaskError: If pattern is invalid
Example:
match("file.txt", "*.txt") # TrueFilter paths matching a glob pattern.
Parameters:
paths(Iterable[str]): Iterable of file pathspattern(str): Glob pattern (supports negation with!)
Returns:
- list[str]: List of matching paths in original order
Raises:
PathmaskError: If pattern is invalid
Example:
filter_paths(["a.txt", "b.md", "c.txt"], "*.txt")
# ["a.txt", "c.txt"]Compile a glob pattern for repeated matching.
Parameters:
pattern(str): Glob pattern
Returns:
- CompiledPattern: Compiled pattern object
Raises:
PathmaskError: If pattern is invalid
Example:
compiled = compile_pattern("src/**/*.js")
compiled.match("src/main.js") # TrueTest if a path matches a compiled pattern.
Parameters:
path(str): File path to match
Returns:
- bool: True if path matches pattern
Example:
pattern = compile_pattern("*.txt")
pattern.match("file.txt") # TrueException raised for invalid patterns.
Example:
from pathmask import PathmaskError
try:
match("file.txt", "file.{txt")
except PathmaskError as e:
print(f"Invalid pattern: {e}")Install dev dependencies:
pip install pytest pytest-covRun tests:
pytest tests/Run with coverage:
pytest --cov=src/pathmask --cov-report=html tests/View coverage report:
open htmlcov/index.htmlMIT License - see LICENSE file for details