fs.glob()

Finds files matching one or more glob patterns, yielding each path as the directory tree is walked.

Signature
fs.glob(pattern[, options], callback)
  • Added in Node.js v22.0.0

Parameters

ParameterTypeDescription
$patternstring | string[]One or more glob patterns. Supports * for a single path segment, ** for any depth, ? for one character and {a,b} for alternatives.
$optionsoptionalObjectTraversal options.
$options.cwdoptionalstring | URL= process.cwd()Directory the patterns are resolved against and results are reported relative to.
$options.excludeoptionalFunction | string[]= undefinedA predicate returning true to drop an entry, or an array of glob patterns to exclude. Negation patterns such as '!foo.js' are not supported.
$options.followSymlinksoptionalboolean= falseFollow symbolic links to directories while expanding **. Detected link cycles are not traversed recursively.
$options.withFileTypesoptionalboolean= falseYield Dirent objects instead of path strings.

Return value

undefinedNothing. The callback is invoked as callback(err, matches) with an array of matching paths, relative to options.cwd. The promise form, fsPromises.glob(pattern[, options]), returns an AsyncIterator that yields each match as it is found.

Errors

The callback receives an error only when the traversal itself fails, for example EACCES on an unreadable directory; a pattern that matches nothing is not an error and simply produces an empty array or an iterator that yields no values.

Changelog

  • PHP v26.1.0Added the followSymlinks option. Before this, symlinked directories were never descended into when expanding **.
  • PHP v24.1.0, v22.17.0The cwd option accepts URL instances.
  • PHP v24.0.0, v22.17.0The API was marked stable; earlier releases emitted an experimental warning.
  • PHP v23.7.0, v22.14.0The exclude option accepts an array of glob patterns, not only a filter function.
  • PHP v22.2.0Added the withFileTypes option.

fs.glob() walks the filesystem and reports the paths matching a shell-style pattern: * for one path segment, ** for any depth, ? for a single character, {a,b} for alternatives. It removed the main reason most projects carried a third-party glob dependency.

Results are relative to cwd, which defaults to process.cwd(). The promise form is an AsyncIterator, so you can act on each match as the walk finds it instead of waiting for the whole tree — worth having on a large repository. The callback form buffers everything and hands you one array.

Details worth knowing

  • pattern may be an array; matches from all patterns are merged.
  • exclude takes a predicate returning true to drop an entry, or (since v22.14.0 / v23.7.0) an array of glob patterns. Negation patterns like '!foo.js' are never supported.
  • Excluding a directory prunes it, so 'node_modules/**' avoids descending rather than filtering afterwards — a large difference in speed.
  • withFileTypes: true yields Dirent objects; note their parentPath is absolute even though plain string results are relative to cwd.
  • Symlinked directories are skipped under ** unless followSymlinks is on (v26.1.0+).
  • Order is filesystem order, not sorted. Sort it yourself if output stability matters.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Collect every test file in a repository without adding a glob dependency.
  • Build a lint or codemod target list while skipping node_modules and build output.
  • Stream-process matches on a huge tree with for await, so work starts before the walk ends.
  • Find all Markdown files under a docs directory to generate an index.

Frequently asked questions

Does Node.js have a built-in glob, so I can drop the glob package?

Yes — fs.glob(), fsPromises.glob() and fs.globSync() shipped in Node 22.0.0 and were marked stable in 22.17.0 / 24.0.0. They cover *, **, ? and {a,b} brace expansion, which is what most projects used the npm package for; extglob syntax and negation patterns are not supported.

How do I exclude node_modules from fs.glob?

Pass exclude: ['node_modules/**'] (Node 22.14.0 and later) or exclude: (p) => p.startsWith('node_modules') on any 22.x release. Excluding a directory prunes the walk instead of filtering results afterwards, so it is much faster than matching everything and rejecting later; note that negation patterns like '!node_modules' do not work.

Are fs.glob results absolute or relative paths?

They are relative to the cwd option, which defaults to process.cwd(). The exception is withFileTypes: true, where each Dirent's parentPath is absolute — so join d.parentPath with d.name for a full path, or use path.relative() if you need the relative form back.

More examples

Dirent results with withFileTypes

Each line shows a Dirent's name, its directory and its type. The reason to ask for Dirents is that the type is already known from the directory walk, so d.isFile() and d.isDirectory() cost nothing — checking the same thing with fs.stat() would add one syscall per match. The path.relative() call is there because parentPath comes back absolute while the default string results are relative to cwd.

Example · javascript
import fsp from 'node:fs/promises';
import path from 'node:path';
import { glob } from 'node:fs/promises';

await fsp.mkdir('proj/src/lib', { recursive: true });
await fsp.writeFile('proj/src/app.js', '');
await fsp.writeFile('proj/src/lib/math.js', '');

for await (const d of glob('proj/**/*.js', { withFileTypes: true })) {
  // d.parentPath is ABSOLUTE, unlike the plain string form.
  console.log(d.name, '| in:', path.relative(process.cwd(), d.parentPath), '| isFile:', d.isFile());
}

await fsp.rm('proj', { recursive: true, force: true });

Multiple patterns, a different cwd, and the sync form

The first list holds src/README.md, src/app.js and src/lib/math.js — merged from both patterns, reported relative to the cwd option, with node_modules pruned rather than filtered afterwards. The second line shows fs.globSync() returning a plain array, and a single * matching only within one directory level, so proj/src/lib/math.js is absent. Note that the string-array form of exclude requires Node 22.14.0 or newer.

Example · javascript
import fs from 'node:fs';
import fsp from 'node:fs/promises';
import { glob } from 'node:fs/promises';

await fsp.mkdir('proj/src/lib', { recursive: true });
await fsp.mkdir('proj/node_modules/dep', { recursive: true });
await fsp.writeFile('proj/src/app.js', '');
await fsp.writeFile('proj/src/lib/math.js', '');
await fsp.writeFile('proj/src/README.md', '');
await fsp.writeFile('proj/node_modules/dep/index.js', '');

const found = [];
for await (const p of glob(['**/*.js', '**/*.md'], {
  cwd: 'proj',
  exclude: ['node_modules/**'],
})) found.push(p);

console.log('relative to cwd:', found.sort());
console.log('globSync:', fs.globSync('proj/src/*.js').sort());

await fsp.rm('proj', { recursive: true, force: true });

Discussion

  • Be the first to comment on this lesson.