Glob Pattern Tester
Test glob patterns against file paths and see the regular expression they become, covering the differences between shell globbing and library implementations.
One star and two stars are not the same wildcard
Compiled to a regular expression the whole difference is one character class:
* becomes [^/]* and ** becomes .*. One
refuses to cross a separator and the other does not care.
| Pattern | Matches | Compiles to |
|---|---|---|
*.js | 6 | ^(?!\.)[^/]*\.js$ |
**.js | 11 | ^(?!\.).*\.js$ |
**/*.js | 11 | ^(?!\.)(?:.*\/)?[^/]*\.js$ |
*/*.js | 3 | ^(?!\.)[^/]*\/[^/]*\.js$ |
src/*.js | 2 | ^(?!\.)src\/[^/]*\.js$ |
src/**/*.js | 4 | ^(?!\.)src\/(?:.*\/)?[^/]*\.js$ |
Everything *.js finds, **.js also finds, and
5 more. ? belongs to the first
family: exactly one character, and not a separator either, so
?/a.js can never match anything at all.
And **/ is a third thing again: it compiles to
(?:.*\/)?, an optional group. That optionality is the entire
reason **/*.js is the idiom for "anywhere" — without it the pattern would
demand at least one directory and quietly skip the files at the root, which is exactly what
*/*.js does.
Testing against a list proves difference, not sameness
Matching a pattern against paths you paste is exactly the right way to build one. It is not a way to show two patterns are the same. On a short list these pick out identical files:
| Pattern A | Pattern B | Probe path | A | B |
|---|---|---|---|---|
*.js | ?.js | ab.js | yes | no |
?.js | [ab].js | c.js | yes | no |
*.js | {a,b}.js | abc.js | yes | no |
Every one of those pairs agrees on a list like
a.js, b.js, readme.md and disagrees on one extra file. The honest use of
this tool is the other direction: if two patterns disagree on your list, that proves
they differ. If they agree, you have learned nothing about the paths you did not paste, which
is where the surprise usually lives.
The dotfile guard only covers the root
With "match dotfiles" off, the compiler adds (?!\.) — a check that the path does
not start with a dot. It sits at position zero of the whole path, once. So *
correctly refuses .hidden , and src/* happily matches
src/.secret.js, because by then the
lookahead has long since passed. A shell or a .gitignore hides dotfiles at every level of the
tree; this hides them at the top only. That is a real limitation, left as it is on purpose —
fixing it properly means a lookahead per path segment, which would change the result of many
existing patterns. The regex box above always shows you exactly what was built.
One thing that was broken and is not now
Nested braces did not work. {a,{b,c}}.js matched a.js and then,
oddly, the literal filenames {b.js and c}.js.
| Pattern | Compiles to | Matches |
|---|---|---|
{a,b}.js | ^(?!\.)(?:a|b)\.js$ | a.js, b.js |
{a,{b,c}}.js | ^(?!\.)(?:a|(?:b|c))\.js$ | a.js, b.js, c.js |
{a,{b,{c,d}}}.js | ^(?!\.)(?:a|(?:b|(?:c|d)))\.js$ | a.js, b.js, c.js, d.js |
*.{js,ts} | ^(?!\.)[^/]*\.(?:js|ts)$ | a.js, ab.js, abc.js, b.js, c.js, d.js, a.ts |
The outer scan tracked brace depth correctly to find the matching }, and then
split the body on every comma without tracking depth at all — so
a,{b,c} came apart into a, {b and
c}. Two unterminated braces, which the compiler falls back to treating
as literal text, hence the strange filenames. It now splits on top-level commas only and
nests to any depth. Patterns without nesting compile to exactly the same regex as before.
How to use
- Enter a glob pattern and some paths to test.
- See which paths match and which do not.
- Read the equivalent regular expression.
- Check how the pattern handles hidden files and directory separators.
Frequently asked questions
What is the difference between one asterisk and two?
A single asterisk matches within one path segment and stops at a slash; a double asterisk crosses directory boundaries. So one asterisk followed by .js matches files in the current directory only, while the double-asterisk form matches at any depth. This is the single most important distinction in globbing.
Do globs match hidden files?
Usually not by default. Most implementations exclude files beginning with a dot unless the pattern explicitly starts with one, following shell convention. This surprises people whose build ignores a dotfile they expected to be caught.
Is a glob a regular expression?
No, though it converts to one. Globs are a much smaller language designed for filenames — no alternation in the base syntax, no quantifiers, no capture groups. That limitation is deliberate: patterns for file paths should be readable at a glance.
What does the question mark match?
Exactly one character, and not a slash. It is the glob equivalent of a regular expression dot with the separator excluded, useful for matching fixed-length names or a single unknown character in an extension.
Do all tools implement globs the same way?
No, and the differences bite. Brace expansion, extended globs, whether a trailing double asterisk matches zero directories, and case sensitivity all vary between shells and libraries. A pattern that works in your shell may behave differently in a build tool that implements its own matcher.
How do I match a literal asterisk?
Escape it with a backslash, or place it in a character class in implementations that support them. Filenames containing glob characters are legal and awkward, which is one reason they are worth avoiding when naming files.
🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.