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*/barshould 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.\xmatchesx,\*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}- matchesaorborc. A component can be empty, e.g.{,a,b}matches either nothing oraorb. Multiple path segments,*,**, etc are all allowed within{}. To specify a path containing,within{}, escape it (\,).[abc]- matches a single character (aorborc).[]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/")),
)