glob

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

README

glob

glob compiles path-aware glob patterns and matches them against strings. It supports component-local wildcards, component-spanning globstars, character classes, and nested brace alternatives without accessing the filesystem.

go get github.com/greatliontech/glob

Usage

Compile a pattern once and reuse it:

pattern, err := glob.Compile("{cmd,internal}/**/*.{go,mod}")
if err != nil {
	return err
}

if pattern.Match("internal/net/http.go") {
	// The complete path matched.
}

Use MustCompile for patterns that are constants under application control:

var goFiles = glob.MustCompile("**/*.go")

Compiled patterns are immutable and safe for concurrent use. Match performs no heap allocations. For an input of N runes and source pattern of M runes, matching takes O(N*M) time and O(M) working memory; for a fixed pattern, time is linear in the input length.

Compared With Go Regexp

glob is a narrower language than regexp: it provides path-component semantics directly, while an equivalent regular expression must encode separators, globstar, alternatives, and whole-input anchors explicitly. Use regexp when general regular-expression syntax or captures are required.

The repository benchmarks each glob against an equivalent compiled, anchored Go regexp. One representative run produced:

Case Glob pattern Input glob regexp glob advantage
Literal match src/main.go src/main.go 4.59 ns/op 67.0 ns/op 14.6x
Extension match *.go main.go 16.7 ns/op 200 ns/op 12.0x
Recursive extension match **/*.go cmd/internal/deep/main.go 4.75 ns/op 551 ns/op 116x
Alternatives match {cmd,internal}/**/*.{go,mod} internal/net/http/main.go 82.2 ns/op 595 ns/op 7.2x
Unicode class match [α-ω]*.go λογος.go 60.5 ns/op 251 ns/op 4.1x

Both matchers reported zero allocations in these cases. Results are from Go 1.26.5 on linux/amd64 with an Intel Core Ultra 7 258V and are illustrative, not an API guarantee. Run the complete matrix on the target system with:

go test -run '^$' -bench '^BenchmarkMatch$' -benchmem

The equivalent regexp sources and all benchmark inputs are in benchmark_test.go.

Pattern Language

Construct Meaning
* Zero or more runes within one component
? One rune within one component
[abc] One listed rune within one component
[a-z] One rune in an inclusive range
[!a-z] One rune outside the class
** Zero or more complete components when it forms a complete component
{go,mod} One alternative; groups may be nested and may span components
\ Quote the next pattern rune, except that an escaped configured separator outside a class remains structural

Matching always consumes the entire input. Ordinary wildcards never consume the separator. ** is a globstar only when it is exactly two unescaped stars written together without crossing a brace-group boundary and forming a complete component. Stars in pre**post, ***, and *{*,x} behave as ordinary stars and cannot cross the separator.

Examples with the default / separator:

Pattern Matches Does not match
*.go main.go cmd/main.go
**/*.go main.go, cmd/main.go main.mod
a/**/b a/b, a/x/y/b a/x
{cmd,internal}/**/*.go internal/net/http.go pkg/net/http.go

Leading, repeated, and trailing separators are significant. Matching is case-sensitive, performs no Unicode normalization, gives leading dots no special treatment, and does not clean . or .. components.

See docs/specs/glob.md for the complete language and error contract.

Separators

Slash is the default separator on every operating system. Select another Unicode scalar value at compile time:

hosts := glob.MustCompile("**.example.com", glob.WithSeparator('.'))
fmt.Println(hosts.Match("api.eu.example.com")) // true

The configured separator applies to both the pattern and input. Outside a character class, an escaped configured separator is always structural. Escaping is required where the separator would otherwise act as pattern syntax at that position. Callers matching native filesystem paths must choose a separator and convert paths themselves; the package deliberately does not infer os.PathSeparator.

Errors And Limits

Compile validates the complete pattern and returns a *glob.CompileError for invalid syntax, invalid UTF-8, invalid configuration, or a pattern longer than MaxPatternBytes. CompileError.Offset is a byte offset into the source pattern, or -1 for configuration errors. Error messages and the exact offset chosen when more than one construct is malformed are not compatibility contracts.

Input strings need not contain valid UTF-8. Matching follows Go range-loop decoding, so each invalid byte is treated as U+FFFD.

Integration

  • Compile when loading configuration, retain the resulting *Pattern, and reject the containing rule if compilation fails.
  • Convert or normalize paths before calling Match if the application needs those semantics. The pattern and input must use the same separator.
  • Treat Match as whole-path matching. Add **/ or another explicit pattern construct when matching at arbitrary component depth.
  • Audit semantics before replacing another glob implementation. This package accepts empty patterns, treats ^ as a class literal rather than negation, matches dot-prefixed components normally, and supports braces and globstar; those choices commonly differ from path/filepath.Match, shells, and watcher protocols.
  • Do not concatenate literal user text into a pattern without escaping it for the pattern position where it will appear.

License

Copyright 2026 Great Lion Technologies. Licensed under the Apache License 2.0.

Documentation

Overview

Package glob compiles path-aware glob patterns for matching strings.

Patterns match the entire input. By default, slash separates path components on every operating system. WithSeparator selects another separator when compiling a pattern. The package does not access the filesystem or clean, normalize, or otherwise modify paths.

The pattern language provides:

  • * to match zero or more runes within one component
  • ? to match one rune within one component
  • [...] and [!...] character classes within one component
  • ** written together as a complete component to match zero or more components
  • {...,...} alternatives, including nested and empty alternatives
  • backslash to quote the next pattern rune, except that an escaped configured separator outside a class remains structural

A compiled Pattern is immutable and safe for concurrent use. Matching performs no heap allocations. For an input of N runes and source pattern of M runes, matching takes O(N*M) time and O(M) working memory; for a fixed pattern, time is linear in the input length. Compile patterns once and reuse them when matching multiple inputs.

Example
package main

import (
	"fmt"

	"github.com/greatliontech/glob"
)

func main() {
	pattern := glob.MustCompile("{cmd,internal}/**/*.{go,mod}")

	for _, path := range []string{
		"cmd/main.go",
		"internal/net/http.go",
		"cmd/main.sum",
		"main.go",
	} {
		fmt.Printf("%s: %t\n", path, pattern.Match(path))
	}

}
Output:
cmd/main.go: true
internal/net/http.go: true
cmd/main.sum: false
main.go: false

Index

Examples

Constants

View Source
const MaxPatternBytes = 4096

MaxPatternBytes is the largest pattern accepted by Compile.

Variables

This section is empty.

Functions

This section is empty.

Types

type CompileError

type CompileError struct {
	Offset  int
	Message string
}

CompileError describes a pattern compilation failure. Offset is a byte offset into the pattern, or -1 when the error concerns configuration.

func (*CompileError) Error

func (e *CompileError) Error() string

type Option

type Option func(*config)

Option configures pattern compilation. Passing a nil Option to Compile or MustCompile is invalid.

func WithSeparator

func WithSeparator(separator rune) Option

WithSeparator configures separator as the path separator. The default is '/'. Separator must be a Unicode scalar value. If multiple separator options are supplied, the last one takes effect.

Example
package main

import (
	"fmt"

	"github.com/greatliontech/glob"
)

func main() {
	pattern := glob.MustCompile("**.example.com", glob.WithSeparator('.'))

	fmt.Println(pattern.Match("example.com"))
	fmt.Println(pattern.Match("api.eu.example.com"))
	fmt.Println(pattern.Match("example.net"))

}
Output:
true
true
false

type Pattern

type Pattern struct {
	// contains filtered or unexported fields
}

Pattern is an immutable compiled glob pattern. A Pattern is safe for concurrent use by multiple goroutines. Its zero value is invalid; methods must be called on a non-nil Pattern returned by successful compilation.

func Compile

func Compile(pattern string, options ...Option) (*Pattern, error)

Compile compiles pattern into an immutable matcher. Pattern must be valid UTF-8 and no longer than MaxPatternBytes. Options are applied in order. Compile returns a CompileError for invalid syntax or configuration.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/greatliontech/glob"
)

func main() {
	_, err := glob.Compile("[z-a]")
	var compileErr *glob.CompileError
	if errors.As(err, &compileErr) {
		fmt.Printf("invalid pattern at byte %d\n", compileErr.Offset)
	}

}
Output:
invalid pattern at byte 2

func MustCompile

func MustCompile(pattern string, options ...Option) *Pattern

MustCompile is like Compile but panics if pattern cannot be compiled.

func (*Pattern) Match

func (p *Pattern) Match(input string) bool

Match reports whether input matches the complete pattern.

func (*Pattern) String

func (p *Pattern) String() string

String returns the pattern supplied to Compile.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL