A better glob library for Go
- ✅ Glob in a deterministic order, like
fs.WalkDir
. - ✅ Support the classics like
?
and*
, and also modern conveniences like**
,{x,y,z}
,[abc]
, and[^abc]
. - ✅ Expand
~
to the current user's homedir. - ✅ Optionally traverse directory symlinks.
- ✅ Avoid walking directories unnecessarily -
globbing
foo*/bar
should only walk inside directories starting withfoo
, not other directories. - ✅ Pass walk errors (e.g. permissions errors) to the callback.
- ✅ Supports globbing over any
io.FS
, not just the host filesystem. - ✅ Supports globbing on Windows with Windows-style paths, by default.
Also the implementation shouldn't be totally inscrutable. It is based on a
state machine, and I have attempted to cleanly separate each parsing phase.
You can convert a pattern to GraphViz format, that you can then convert into a
diagram, by calling Pattern.WriteDot
. zzglob
includes a tool called zzdot
which can do this for you, e.g.:
go run ./cmd/zzdot '[abcd]{*g,h*,i/j}/**/k' | dot -Tsvg > example.svg
- ⌚️ Improving the tests.
- 🧠 Add support for even more syntax
\
- used to escape the next character in the pattern.\x
matchesx
,\*
matches*
./
- the path separator. Separates segments of each path. Matches itself only.?
- matches exactly one character, except for/
.*
- matches zero or more characters, except for/
.**
- matches zero or more characters, including/
. Since it can be used to mean zero or more path components,/**/
also matches/
.{a,b,c}
- matchesa
orb
orc
. A component can be empty, e.g.{,a,b}
matches either nothing ora
orb
. Multiple path segments,*
,**
, etc are all allowed within{}
. To specify a path containing,
within{}
, escape it (\,
).[abc]
- matches a single character (a
orb
orc
).[]
is a shorter way to write a match for a single character than{}
.~
- is expanded to be current user's home directory.
Each syntax element can be enabled or disabled individually when calling
Parse
, and the meaning of forward slash and backslash can be swapped
(enabled by default on Windows):
pattern, err := zzglob.Parse(`C:\Windows\Media\*.mid`,
zzglob.ExpandTilde(false),
zzglob.SwapSlashes(true),
zzglob.AllowEscaping(false),
)
Similarly, symlink traversal, slash conversion, and custom fs.FS
can be
supplied to Glob
:
err := pattern.Glob(myWalkDirFunc,
zzglob.TraverseSymlinks(false),
zzglob.TranslateSlashes(true),
zzglob.WithFilesystem(os.DirFS("/secrets/")),
)