Glob API
pathapi.glob
Filename globbing over any pathapi Path.
Modelled on CPython's pathlib glob selectors, reworked to run over anything
that implements _scandir()/iterdir()/is_dir()/name like
pathlib.Path (LocalPath, MemPath, FTPPath, the archive paths).
RECURSIVE = '**'
module-attribute
__all__ = ['RECURSIVE', 'full_match', 'glob', 'parse_pattern', 'select']
module-attribute
full_match(segments, pattern, case_sensitive)
Match segments against a glob pattern that may contain ""
components (pathlib 3.13's PurePath.full_match semantics): a "" matches
zero or more segments, except a trailing "" after other components,
which needs at least one ("a/" does not match "a").
The root is a field of its own, as in the path's text: a rooted pattern names it with its leading "/", a lone "" never matches it (a lone "" matches one or more characters), and a "" followed by more components reaches it only together with a name after it ("/x" matches "/a/x", not "/x"). Empty and "." components are dropped from the pattern. A bracket expression never matches a separator (pathlib's regex lets a negated one).
Runs as a set-of-states automaton, O(len(segments) * len(pattern)), so repeated "**" cannot backtrack exponentially.
Source code in src/pathapi/glob/_patterns.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | |
glob(path, *, dironly=False, root_dir=None, recursive=False, include_hidden=False, case_sensitive=None, native=True, on_error=None, bound_loops=False, recurse_symlinks=False)
Return an iterator which yields the paths matching a pathname pattern.
path is the pattern itself, as a path (e.g. LocalPath("/x/**/*.py")).
The pattern may contain simple shell-style wildcards a la fnmatch. Like
the stdlib glob module, and unlike Path.glob(), hidden entries (names
starting with a dot) are not matched by wildcards and not descended into
by "**" unless include_hidden is true.
If recursive is true, the pattern '' will match zero or more
directories and subdirectories; as the last component it also matches
files on Python 3.13+ or with native=False, and directories only
otherwise. recursive=None decides
from the pattern itself, as Path.glob() does: a "" component enables
it. native= follows the running interpreter's rules, or applies one
rule on every version -- see parse_pattern(). recurse_symlinks=True
lets "**" descend through symlinks to directories, see select().
The pattern is validated when this is called and the paths are selected lazily. The path's anchor (a drive, an extended-length drive prefix) is never a wildcard, whatever characters it holds.
Source code in src/pathapi/glob/_selection.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
parse_pattern(pattern, *, native=True)
Split a relative glob pattern (a /-separated string or a
Pathname) into its components, and report whether it ended with a
separator (directories only).
Raises ValueError for an empty pattern and NonRelativePatternError
for an absolute one, as pathlib.Path.glob() does. Empty and "."
components are dropped.
native=True (the default) follows the running interpreter on the two
rules pathlib changed mid-series: a trailing "/" is ignored before 3.11
(it selects directories only from 3.11), and a component that merely
CONTAINS "" ("a") raises ValueError before 3.13. native=False
applies one rule on every version instead -- a trailing "/" always
selects directories only, "a**" is always a plain wildcard -- so a
pattern gives the same answer on every interpreter and every backend.
Source code in src/pathapi/glob/_patterns.py
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
select(base, parts, *, dironly=False, recursive=True, include_hidden=True, case_sensitive=None, native=True, on_error=None, bound_loops=False, recurse_symlinks=False)
Yield the paths under base matching the pattern components parts
(see parse_pattern()); the engine behind Path.glob().
Directory listings go through _scandir(); an OSError from listing a
missing or non-directory path selects nothing. "" (when recursive)
decides recursion from the listing's non-following stat, so it never
descends into a directory symlink and always terminates. A trailing ""
also selects files on Python 3.13+ and directories only before, which is
the third rule native=False pins: it then selects files on every
version (3.13's rule, the one current pathlib applies).
With recurse_symlinks=True "**" also descends through a symlink to a
directory, as pathlib 3.13 does, and ends where that would loop: a link
to a directory the descent is already inside (st_dev/st_ino) is an
entry but is not entered, and so is any link beyond the 40th in one
descent where the stat has no identity.
Source code in src/pathapi/glob/_selection.py
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | |