Glob patterns are simple wildcards used to match file and directory names —
the syntax behind *.js, .gitignore rules, and shell commands like
rm *.log. They're easier than regex but work differently, and the exact rules
vary by tool. This reference covers the core wildcards, character classes,
globstar, brace expansion, and extended globs, with examples for each.
Important: globs are not regular expressions. In a glob, * means "any
characters" — there's no separate . metacharacter, and quantifiers like +
only exist in extended-glob modes.
Basic Wildcards
The core glob syntax, supported almost everywhere (shells, .gitignore, most
libraries).
| Pattern | Matches | Example |
|---|---|---|
* | Any number of characters (not /) | *.js → app.js, index.js |
? | Exactly one character | file?.txt → file1.txt, fileA.txt |
[abc] | One character from the set | file[12].txt → file1.txt, file2.txt |
[a-z] | One character in the range | [a-c]*.js → files starting a–c |
[!abc] | One character not in the set | [!0-9]* → doesn't start with a digit |
[^abc] | Negation (some tools use ^) | same as [!abc] in many tools |
Globstar (Recursive Matching)
** matches across directory boundaries. Support varies — enabled by default in
.gitignore, many build tools, and shells with globstar turned on.
| Pattern | Matches | Example |
|---|---|---|
** | Any number of directories, recursively | src/**/*.js → all .js under src |
**/ | Zero or more directory levels | **/test/ → any test folder at any depth |
**/* | Everything recursively | **/* → all files in all subfolders |
a/**/b | b anywhere below a | src/**/utils → utils at any depth under src |
Key difference: a single
*stops at directory boundaries (src/*.jsmatches only the top level ofsrc), while**crosses them.
Brace Expansion
Braces expand into multiple patterns. Common in shells and many glob libraries
(not in standard .gitignore).
| Pattern | Expands to | Example |
|---|---|---|
{a,b,c} | Each item in the list | *.{js,ts} → .js and .ts files |
{1..5} | A numeric range | file{1..3}.txt → file1/2/3.txt |
{a..d} | A character range | {a..c}.log → a.log, b.log, c.log |
{,foo} | Optional part (empty or "foo") | file{,-old}.txt → file.txt, file-old.txt |
Extended Globs (extglob / micromatch)
Regex-like operators available in Bash extglob mode, and in libraries like
micromatch/minimatch. Not universally supported.
| Pattern | Meaning | Example |
|---|---|---|
?(pattern) | Zero or one occurrence | file?(s).txt → file.txt, files.txt |
*(pattern) | Zero or more occurrences | a*(b) → a, ab, abb |
+(pattern) | One or more occurrences | a+(b) → ab, abb |
| `@(a | b)` | Exactly one of the patterns |
!(pattern) | Anything except the pattern | !(*.test).js → non-test JS files |
.gitignore Specifics
Glob rules that behave uniquely inside .gitignore files.
| Pattern | Meaning |
|---|---|
*.log | Ignore all .log files, anywhere |
build/ | Ignore the build directory (trailing slash = dir only) |
/config | Ignore config only at the repo root (leading slash) |
!important.log | Un-ignore a file (negation / exception) |
**/temp | Ignore any temp folder at any depth |
docs/** | Ignore everything inside docs |
# comment | A comment line (ignored) |
Common Patterns
Copy-and-adapt globs for everyday tasks.
| Use case | Pattern |
|---|---|
| All JavaScript files | *.js |
| JS and TS files | *.{js,ts} |
| All files recursively | **/* |
| All JS under a folder, recursively | src/**/*.js |
| All images | *.{jpg,jpeg,png,gif,webp} |
| Everything except tests | !(*.test).js (extglob) |
| Hidden dotfiles | .* |
| Any file in any test folder | **/test/** |
| Files with a single-digit suffix | file[0-9].txt |
Golden Rules for Glob Patterns
- A glob is not a regex —
*means "any characters,".is a literal dot, and there are no anchors. Don't reach for regex habits. *stops at/,**doesn't — use globstar when you need to match across directory levels.- Check your tool's support — brace expansion, globstar, and extglob are
not universal. What works in Bash may not work in
.gitignoreor a given library. - Quote globs in shells to delay expansion —
"*.js"passes the literal pattern to a program instead of letting the shell expand it first. - Order matters in
.gitignore— a later negation (!file) can re-include something an earlier rule ignored, but not if a parent directory is excluded.
Frequently Asked Questions
What is a glob pattern?
A glob pattern is a wildcard expression used to match filenames and paths, such
as *.txt for all text files. It's the matching syntax used by shells,
.gitignore, and many build tools.
What is the difference between glob and regex?
Globs are a small wildcard language for matching file paths, where * means
"any characters." Regular expressions are a far more powerful, general-purpose
text-matching language with anchors, quantifiers, and groups. They share some
symbols but behave differently.
What does ** (globstar) do?
** matches directories recursively, crossing folder boundaries. For example,
src/**/*.js matches every .js file at any depth under src, while src/*.js
matches only the top level.
What is the difference between * and **?
A single * matches within one directory level and stops at /. A double **
matches across multiple directory levels. Use ** for recursive matching.
How do I match multiple extensions with a glob?
Use brace expansion: *.{js,ts,jsx,tsx} matches all four extensions. Note that
brace expansion isn't supported everywhere, including standard .gitignore.
How do I exclude files in a .gitignore?
Prefix a rule with ! to negate it and re-include a previously ignored file —
for example, ignore *.log but keep one with !important.log. This won't work
if the file's parent directory is already excluded.