search

Find objects whose key matches a glob (default), regex, substring, or exact pattern. Streams matches as an async iterable, walking every page like listAll, with a glob's literal prefix pushed down automatically.

files.search(pattern, options?)

Find objects whose key matches pattern, walking every page like listAll. It's a streaming async iterable of StoredFile, so it stays memory-bounded on large buckets and you can break to stop early.

// Glob is the default: `*` stays within a path segment, `?` matches one char.
for await (const file of files.search("avatars/*.png")) {
  console.log(file.key, file.size);
}

// Collect into an array when you want them all at once:
const pdfs = await Array.fromAsync(files.search("invoices/2024/*.pdf"));

Matching is against the caller-facing key, so a client prefix on the instance is already stripped before the pattern is tested.

Glob syntax

"glob" mode uses standard glob semantics, powered by picomatch:

  • * — any run of characters within a path segment (does not cross /).
  • ** — a globstar segment that spans path segments. Write it as its own segment: photos/**/*.jpg matches at any depth, including zero subfolders.
  • ? — a single non-/ character.
  • [a-z], {a,b} — character classes and brace alternation.
  • !pattern — negation (matches everything except).

The pattern is anchored to the whole key, and dotfiles are matched (object keys are opaque, not hidden files). A glob with no wildcards is an exact match, not a substring — files.search("report.pdf") matches the key report.pdf and nothing else. Use match: "substring" for "contains".

// Every JPEG at any depth under photos/:
for await (const file of files.search("photos/**/*.jpg")) {
  // photos/cover.jpg, photos/2024/spain/beach.jpg, ...
}

Match modes

Pass a match mode to change how a string pattern is interpreted, or pass a RegExp directly (which always matches by regex and ignores match):

// Regular expression (string form):
files.search("\\.(png|jpe?g)$", { match: "regex" });

// ...or a RegExp instance:
files.search(/\.(png|jpe?g)$/);

// Substring — key contains the text anywhere:
files.search("report", { match: "substring" });

// Exact — key equals the text:
files.search("invoices/2024/q1.pdf", { match: "exact" });

// Case-insensitive (any mode):
files.search("*.PNG", { caseInsensitive: true });

An invalid regex pattern throws a FilesError before the walk begins.

Scoping the walk with prefix

search reads every page under a prefix, following the cursor. For a glob, the literal head of the pattern is pushed down automatically as that prefix, so files.search("uploads/2024/*.pdf") scopes the walk to the uploads/2024 prefix rather than the whole bucket.

Other modes carry no inferable prefix, so for a regex, substring, or caseInsensitive search over a large bucket, pass prefix yourself to bound the walk:

// Only walk logs/ — then regex-match within it:
files.search("error|panic", { match: "regex", prefix: "logs/" });

A glob's auto push-down is disabled when caseInsensitive is set (a provider's prefix filter is case-sensitive), so combine caseInsensitive with an explicit prefix to scope it.

Stopping early

maxResults caps the number of matches yielded; because the walk is lazy, it also stops paging once the cap is hit. Equivalently, break out of the loop.

// First 10 matches, then stop fetching pages:
const recent = await Array.fromAsync(
  files.search("**/*.log", { maxResults: 10 })
);

Provider support

search runs on every adapter, since it's built on listAll — there's no per-provider search capability and nothing to gate. The two listAll caveats carry over: on Netlify Blobs omit limit to walk everything, and the non-recursive Box / OneDrive / SharePoint adapters only see the immediate children of the root folder. An unbounded search with no prefix walks the whole bucket by design.

Options

Prop

Type

The match mode is one of:

Prop

Type

On this page