glob-match

repository·main·Indexed 43 days ago

https://github.com/devongovett/glob-match

An extremely fast Rust library for glob pattern matching (version 0.2.1) featuring linear time complexity and zero allocations. It supports wildcards (*, **), character classes ([a-z]), brace expansion ({a,b}), and negation (!). Key functions include `glob_match` for boolean matching and `glob_match_with_captures` to extract byte ranges of segments matched by wildcards.

Tokens
2.5K
Snippets
9
Records
10
Agent score
6%

What's inside glob-match

  1. Fuzz glob-match using cargo fuzz

    main

    To fuzz glob-match, use cargo fuzz. Refer to the Rust Fuzz Book for setup and installation instructions.

    If you discover artifacts, you can use cargo fuzz fmt [target] [artifact-path] to retrieve the original input that caused the issue.

    $ cargo fuzz fmt both_fuzz fuzz/artifacts/both_fuzz/slow-unit-LONG_HASH
  2. How negation (!) works in glob patterns

    main

    The ! character is used to negate a pattern. A negated pattern matches any string that does not satisfy the original pattern.

    • !*.md matches any string that does not end in .md (e.g., a.js matches, a.md does not).
    • !a/* matches any string that does not start with a/ followed by a segment (e.g., a matches, a/b does not).
    • !*/b matches any string that does not have b as the last segment of a path (e.g., a matches, a/b does not).

    When using negation with recursive patterns like !**/*.md, the pattern matches any string that is not a .md file anywhere in the tree.

    // Negation examples
    assert!(!glob_match("!*.md", ".md"));
    assert!(glob_match("!*.md", "a.js"));
    assert!(glob_match("!*.md", "c.txt"));
    
    // Negating path segments
    assert!(glob_match("!a/*", "a"));
    assert!(!glob_match("!a/*", "a/b"));
  3. How recursive globbing (**) works

    main

    The ** pattern (globstar) allows for matching across directory boundaries.

    • **/*.js will match a.js, a/b.js, and a/b/c/d.js.
    • a/**/b will match a/b and a/x/y/b.
    • a/** matches the directory a and all its contents, including subdirectories.
    • **/a matches any path ending in /a or just a at any depth.

    Crucially, ** can be combined with other patterns, such as a/**/f/*.md, which matches files with a .md extension located in a subdirectory f, where f is at any depth under a.

    Note on empty matches: Patterns like ** can match both the directory itself and its contents (e.g., glob_match("**", "a") is true).

    // Recursive matching examples
    assert!(glob_match("**/*.js", "a/b/c.js"));
    assert!(glob_match("a/b/**/*.js", "a/b/c/d/e.js"));
    assert!(glob_match("a/**/f/*.md", "a/b/c/d/e/f/g.md"));
    
    // Matching the directory itself or contents
    assert!(glob_match("**", "a"));
    assert!(glob_match("a/**", "a/b/c"));
  4. Capture wildcard ranges with glob_match_with_captures

    main

    If you need to extract the specific parts of a path that matched dynamic parts of a glob (like * or **), use glob_match_with_captures. This function returns a Result<Vec<Range<usize>>, ...> (or similar collection of ranges) representing the start and end indices of the matched segments within the original path string. You can then use these ranges to slice the original path.

    use glob_match::glob_match_with_captures;
    
    let glob = "some/**/{a,b,c}/**/needle.txt";
    let path = "some/path/a/to/the/needle.txt";
    let result = glob_match_with_captures(glob, path)
      .map(|v| v.into_iter().map(|capture| &path[capture]).collect());
    
    assert_eq!(result, vec!["path", "a", "to/the"]);
  5. Perform simple glob matching with glob_match

    main

    Use the glob_match function to check if a path matches a given glob pattern. The matching is performed in linear time with zero allocations and no regex compilation.

    use glob_match::glob_match;
    
    assert!(glob_match("some/**/{a,b,c}/**/needle.txt", "some/path/a/to/the/needle.txt"));
  6. Glob pattern syntax reference

    main

    The following syntax is supported for glob patterns:

    SyntaxMeaning
    ?Matches any single character.
    *Matches zero or more characters, except for path separators (e.g. /).
    **Matches zero or more characters, including path separators. Must match a complete path segment (i.e. followed by a / or the end of the pattern).
    [ab]Matches one of the characters contained in the brackets. Character ranges, e.g. [a-z] are also supported. Use [!ab] or [^ab] to match any character except those contained in the brackets.
    {a,b}Matches one of the patterns contained in the braces. Any of the wildcard characters can be used in the sub-patterns. Braces may be nested up to 10 levels deep.
    !When at the start of the glob, this negates the result. Multiple ! characters negate the glob multiple times.
    \A backslash character may be used to escape any of the above special characters.
  7. Extract wildcard captures with `glob_match_with_captures`

    main

    Use glob_match_with_captures to check if a path matches a pattern and simultaneously retrieve the byte ranges (std::ops::Range<usize>) of the segments matched by wildcards (* or **).

    If the pattern does not match, the function returns None. If it matches, it returns Some(Vec<Capture>), where each Capture represents the start and end indices of a matched segment in the path string.

    Note: Captures are created for each distinct wildcard segment encountered.

    use glob_match::glob_match_with_captures;
    
    // Example: capturing the part matched by '*'
    if let Some(captures) = glob_match_with_captures("a*c", "abc") {
        // captures[0] would be 1..3 (the 'bc' part)
        println!("Captured: {:?}", captures);
    }
  8. Match patterns using glob_match

    main

    The glob_match function is the primary API for checking if a string matches a given glob pattern. It supports standard globbing features including wildcards, character sets, and directory traversal.

    Supported Syntax

    • *: Matches any number of characters within a single path segment (does not cross / boundaries unless part of **).
    • **: Matches any number of characters, including directory separators (recursive globbing).
    • ?: Matches exactly one character.
    • [a-z]: Matches a single character within a specified range or set.
    • [^a-z]: Matches a single character NOT within the specified range or set.
    • {a,b}: Matches one of the comma-separated alternatives.
    • !: Used for negation (e.g., !*.md matches anything that is NOT a .md file).
    • []: Used for character sets, including escaping characters like \] or \- to include them in the set.

    Note that * does not match across directory separators, while ** is designed for recursive matching across multiple directory levels.

    // Example: Basic matching
    assert!(glob_match("a?c", "abc"));
    assert!(glob_match("*.js", "z.js"));
    
    // Example: Recursive matching with **
    assert!(glob_match("a/**/*.txt", "a/x/y/z.txt"));
    assert!(glob_match("**/*.js", "a/b/c.js"));
    
    // Example: Character sets and negation
    assert!(glob_match("[^a-c]*", "d"));
    assert!(glob_match("t[a-g]n", "ten"));
    assert!(!glob_match("!*.md", "foo.md"));
    
    // Example: Braces for alternatives
    assert!(glob_match("{a,b,c}", "b"));
    assert!(glob_match("a/{a,b}", "a/b"));
  9. Match a path against a glob pattern with `glob_match`

    main

    Use the glob_match function to check if a given path string matches a glob pattern. It returns true if the path matches the pattern, and false otherwise.

    Supported features include:

    • Wildcards: * (any characters), ? (any single character), and ** (recursive directory matching).
    • Braces: {a,b} for alternation (matching a or b).
    • Character sets: [a-z] for ranges.
    • Escaping: \( and \) to match literal parentheses.
    • Path separators: Handles / and directory structures correctly.
    use glob_match::glob_match;
    
    assert!(glob_match("a{a,b/}*.txt", "aa.txt"));
    assert!(glob_match("a/b/**/c.md", "a/b/d/e/c.md"));
    assert!(!glob_match("a/b/c.md", "a/x/c.md"));
  10. Check if a path matches a glob pattern with `glob_match`

    main

    Use glob_match to determine if a given path string satisfies a glob pattern. This function returns a boolean.

    Supported features include:

    • Wildcards: * (matches anything except separators) and ** (matches anything including separators).
    • Character classes: [abc], [a-z], and negated classes like [!abc] or [^abc].
    • Brace expansion: {foo,bar} matches either foo or bar.
    • Negation: A leading ! can negate the entire pattern.
    • Escaping: Use \ to escape special characters (e.g., \* matches a literal asterisk).
    use glob_match::glob_match;
    
    assert!(glob_match("*.txt", "file.txt"));
    assert!(glob_match("a/**/b", "a/foo/bar/b"));
    assert!(!glob_match("a/*/b", "a/foo/bar/b"));