node-glob: the glob package for Node.js, and what version 13 changed
glob functionality for node.js
At a glance
- What is it?
- The glob package matches files with shell-style patterns in Node.js. It is the reference implementation for pattern matching in the npm ecosystem, and its CLI now lives in a separate package.
- Who is it for?
- Adopt glob when you need shell-style pattern matching in Node.js, especially if you want a Glob object to reuse caches across repeated walks of the same folder. Do not adopt it if you need a command line tool without adding a dependency, since version 13 moved the CLI to glob-bin.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What node-glob solves, and who it is for
Reading a directory tree in Node.js gives you one level at a time. If you want every JavaScript file under a project except the ones in node_modules, you either write a recursive walker or you describe the set with a pattern. glob does the second thing. The README opens with the claim that it matches "files using the patterns the shell uses", which is the whole pitch: the syntax you already type at a prompt works inside a Node.js process.
The audience is Node.js developers who need to enumerate files rather than open a known path. Build tools, test runners, linters, asset pipelines and migration scripts all start by asking which files exist. The README's own examples lean that way: collecting **/*.js while ignoring node_modules, gathering images from two directories at once, or finding files modified in the last hour. If your program never needs to discover paths, this package has nothing to offer you.
How the matching works: patterns, Path objects and caches
The package exposes the same walk through several shapes. glob() and globSync() return arrays. globStream() and globStreamSync() return a Minipass stream that emits matches and then ends. globIterate() and globIterateSync() return iterators, with aliases such as glob.iterate() and glob.sync.iterate(). The README notes that all of these are the same operation with different consumption models.
The interesting part is the Glob class. Constructing one and iterating it lets you walk a tree once and keep the results, and the README says this "allows for much faster walks if you have to look in the same folder multiple times". You can also pass an existing Glob as the options object to a new one, which reuses its settings and caches. That is a real architectural difference from calling glob() repeatedly, because each fresh call starts from nothing.
By default you get strings. With withFileTypes: true you get Path objects from path-scurry, which the README compares to fs.Dirent "but with some more added powers", including fullpath(), isDirectory() and readdirSync(). Adding stat: true attaches Stats fields, which is what makes sorting by mtimeMs or filtering by permission bits possible. The README is explicit that this is "slightly slower", so the richer result is opt-in.
Ignoring is not limited to a string pattern. The ignore option accepts an object with ignored and childrenIgnored callbacks that receive a Path. The README's examples use this to drop markdown files, to skip directories named docs, and to keep only files whose name matches their parent folder. The last one is a good illustration of why a callback beats a pattern: the predicate depends on the relationship between a file and its parent, which a glob string cannot express.
Installing glob and running a first walk
Installation is one npm command. The README carries a note that the npm package name is glob, not node-glob, which it calls "a different thing that was abandoned years ago". That naming trap is worth reading twice before you copy an install line from an old tutorial.
npm i globAfter that, the package can be loaded with ESM import or CommonJS require. The README shows both, and the package.json declares "type": "module" with separate import and require conditions in its exports map, so both paths are published.
import { glob, globSync, Glob } from 'glob'
const jsfiles = await glob('**/*.js', { ignore: 'node_modules/**' })
const images = globSync('{css,public}/*.{png,jpeg}')The first call returns a Promise of matching paths, with node_modules excluded. The second returns an array directly, and the brace form expands to two directories and two extensions. Brace expansion is treated as a shorthand for passing an array of patterns rather than as magic, which matters for the hasMagic() helper described below.
If you expect to scan the same tree more than once, construct a Glob instead of calling glob() twice. The README's example iterates it with for await, and the second Glob can take the first as its options to inherit settings and caches.
const g = new Glob('**/foo', {})
for await (const file of g) {
console.log('found a foo file:', file)
}
const g2 = new Glob('**/bar', g)The CLI moved out of the package in version 13
Anyone upgrading from an older major version should read the command line section carefully. The README states that the glob CLI "has been moved to the glob-bin package, and must be installed separately, as of version 13". The install line is npm install glob-bin.
This is the kind of change that breaks scripts quietly. A shell script or npm script that calls glob after installing glob will fail on version 13 unless glob-bin is added. Nothing in the README suggests the old binary is kept as a shim, so treat the separation as complete. If your build depends on the CLI, the dependency list needs two entries now, and the version of glob-bin has to be tracked alongside glob itself.
The same section explains why the package name matters. Because node-glob is a different, abandoned package, a project that still lists node-glob in its dependencies is not running this code at all. Checking the dependency tree for that name is a quick way to find stale tooling.
Where glob gets awkward: escaping, platform paths and stale stats
The README's most consequential warning is about separators. Glob patterns should always use / even on Windows, because backslash is the escape character. The escape hatch is windowsPathsNoEscape: true, but the README immediately states the cost: in that mode "special glob characters cannot be escaped, making it impossible to match a literal * ? and so on in filenames". So on Windows you choose between escaping and literal matching. There is no option that gives you both, and code that handles user-supplied filenames has to decide which failure it prefers.
The stat: true path has a subtler problem. The README's example for finding recently modified files uses childrenIgnored on directory mtime, then warns that "directory mtime is inconsistent across platforms, so probably better not to, unless you know the system tracks this reliably". That is an honest admission that one of the package's more attractive features, time-based filtering during the walk, is not portable. Filtering after the walk on file mtimes is the safer shape.
Finally, the withFileTypes and stat combination returns Path and Stats objects rather than strings, and the README says this is slightly slower. Code that assumes string results will need rewriting when these options are switched on, because every consumer now calls fullpath() instead of using the value directly. That is a migration cost, not a bug, but it lands on exactly the code paths that were already doing the most work.
glob compared with fast-glob
fast-glob is the alternative that appears most often in the same conversations, and the two differ in emphasis rather than in category. fast-glob is built around returning arrays of strings from a single call, with its own option set for things like concurrency and deep filtering. glob's README frames its own position differently: it calls itself "the most correct and second fastest glob implementation in JavaScript" and points to a comparison section at the bottom of the readme.
The practical difference shows up in the API surface. glob ships a Glob class with reusable caches, a Minipass stream interface, sync and async iterators, and Path objects carrying Stats when asked. fast-glob's model is closer to one function, one array. If your code walks the same directory repeatedly and you want the cache to persist, glob's Glob object is the reason to pick it. If you want a single call that returns strings and nothing else, the extra surface in glob is weight you will not use.
One shared caveat: neither approach removes the need to think about what happens when a pattern matches tens of thousands of files. The README's signal example, AbortSignal.timeout(100), exists precisely because a walk can run longer than you want.
Licence, maintenance and the cost of upgrading
The repository is not archived, and the last push was on 2026-09-19, two days before this writing. The package.json lists version 13.0.6 and the author as Isaac Z. Schlueter. The repository carries a LICENSE.md file, but the licence identifier reported for the project is NOASSERTION, meaning the metadata does not resolve to a recognised SPDX identifier. Anyone embedding this in a product should read LICENSE.md directly rather than trusting a package manager's summary field, and should have their own legal review rather than treating a scanner result as final.
Upgrade cost concentrates in two places. The major version boundary at 13 is where the CLI left the package, so any tooling that shells out to glob needs glob-bin added and versioned separately. The second is the TypeScript build: package.json uses tshy with separate dist/esm and dist/commonjs outputs and an exports map with import and require conditions, so deep imports into internal paths will not resolve. Importing from 'glob' or 'glob/raw' is what the exports map allows. The repository also ships benchmark and profiling scripts (benchmark.sh, prof.sh, patterns.sh) and a changelog.md, which is where a version-by-version account of behaviour changes should be checked before a major upgrade.
Editorial conclusion
Adopt glob when you need shell-style pattern matching in Node.js, especially if you want a Glob object to reuse caches across repeated walks of the same folder. Do not adopt it if you need a command line tool without adding a dependency, since version 13 moved the CLI to glob-bin. Before upgrading, verify that your code imports from the glob package and not the abandoned node-glob name, and check whether you rely on the CLI, which is no longer bundled.
Frequently asked questions
What is node-glob used for?
It matches files using the same patterns a shell uses, returning the matching paths to a Node.js program. Typical uses from the README include collecting all JavaScript files while ignoring node_modules, gathering images across directories, or filtering results by modification time.
What does glob mean in coding?
A glob is a pattern syntax for matching file paths, using wildcards such as * and ? plus brace expansion like {png,jpeg}. The README notes that brace expansion is treated as turning one string into an array of strings rather than as a magic character, unless magicalBraces is set.
What is node glob?
It is the glob package for Node.js, published on npm under the name glob. The README warns that node-glob is a different package that was abandoned years ago, so the install line is npm i glob.
node glob vs fast glob: how do they differ?
The README describes glob as the most correct and second fastest glob implementation in JavaScript and links to its own comparison section. In API terms, glob offers a Glob class with reusable caches, Minipass streams, iterators and Path objects, while fast-glob is centred on returning arrays of strings from a single call.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/isaacs-node-glob)