> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
> Use this file to discover all available pages before exploring further.

# Glob Pattern Matching

> Match files using glob patterns with Bun's fast glob implementation

Bun provides a fast, cross-platform glob matcher for finding files using wildcard patterns. It's built in Zig and optimized for performance.

## Basic Usage

```ts theme={null}
import { Glob } from "bun";

// Create a glob pattern
const glob = new Glob("**/*.ts");

// Scan for matching files
for await (const file of glob.scan(".")) {
  console.log(file); // "src/index.ts", "test/util.ts", etc.
}
```

## Glob Patterns

### Wildcards

```ts theme={null}
// * matches any characters except /
const glob = new Glob("*.txt");
// Matches: file.txt, data.txt
// Not: dir/file.txt

// ** matches any characters including /
const glob2 = new Glob("**/*.js");
// Matches: file.js, src/index.js, src/lib/util.js

// ? matches single character
const glob3 = new Glob("file?.txt");
// Matches: file1.txt, fileA.txt
// Not: file.txt, file10.txt
```

### Character Classes

```ts theme={null}
// [abc] matches any character in brackets
const glob = new Glob("file[123].txt");
// Matches: file1.txt, file2.txt, file3.txt

// [a-z] matches range
const glob2 = new Glob("[a-z]*.js");
// Matches: app.js, utils.js
// Not: App.js, 1.js

// [!abc] matches any character not in brackets
const glob3 = new Glob("*[!0-9].txt");
// Matches: data.txt, fileA.txt
// Not: file1.txt, data5.txt
```

### Braces

```ts theme={null}
// {a,b,c} matches alternatives
const glob = new Glob("*.{js,ts,jsx,tsx}");
// Matches: index.js, App.tsx, util.ts

// Can be nested
const glob2 = new Glob("{src,test}/**/*.{js,ts}");
// Matches: src/index.js, test/util.ts

// Can contain multiple patterns
const glob3 = new Glob("file.{txt,md,json}");
// Matches: file.txt, file.md, file.json
```

### Negation

```ts theme={null}
// ! at start negates pattern
const glob = new Glob("!*.test.js");
// Matches everything except test files
```

## Scanning Files

### Async Iteration

Most efficient for large directories:

```ts theme={null}
const glob = new Glob("**/*.js");

for await (const file of glob.scan("./src")) {
  console.log(file);
}
```

### Array Result

Collect all matches:

```ts theme={null}
const glob = new Glob("**/*.ts");
const files = await Array.fromAsync(glob.scan("."));
console.log(files);
// ["src/index.ts", "src/util.ts", ...]
```

### Sync Scanning

```ts theme={null}
const glob = new Glob("*.json");
const files = glob.scanSync(".");
// Returns array of matches
```

## Scan Options

### Current Working Directory

```ts theme={null}
const glob = new Glob("*.js");

// Scan from specific directory
for await (const file of glob.scan("/path/to/dir")) {
  console.log(file);
}

// Use options object
for await (const file of glob.scan({ cwd: "./src" })) {
  console.log(file);
}
```

### Dot Files

Include hidden files:

```ts theme={null}
const glob = new Glob("*");

// Exclude dot files (default)
for await (const file of glob.scan({
  cwd: ".",
  dot: false,
})) {
  console.log(file); // Won't include .gitignore, .env, etc.
}

// Include dot files
for await (const file of glob.scan({
  cwd: ".",
  dot: true,
})) {
  console.log(file); // Includes .gitignore, .env, etc.
}
```

### Absolute Paths

Return full paths instead of relative:

```ts theme={null}
const glob = new Glob("**/*.js");

for await (const file of glob.scan({
  cwd: "./src",
  absolute: true,
})) {
  console.log(file); // "/Users/me/project/src/index.js"
}
```

### Only Files

Exclude directories from results:

```ts theme={null}
const glob = new Glob("**/*");

for await (const file of glob.scan({
  onlyFiles: true, // default
})) {
  console.log(file); // Only files, no directories
}

for await (const path of glob.scan({
  onlyFiles: false,
})) {
  console.log(path); // Includes directories too
}
```

### Follow Symlinks

```ts theme={null}
const glob = new Glob("**/*.js");

for await (const file of glob.scan({
  followSymlinks: true,
})) {
  console.log(file); // Follows symlinked directories
}
```

### Throw on Broken Symlinks

```ts theme={null}
const glob = new Glob("**/*");

try {
  for await (const file of glob.scan({
    followSymlinks: true,
    throwErrorOnBrokenSymlink: true,
  })) {
    console.log(file);
  }
} catch (err) {
  console.error("Broken symlink:", err);
}
```

## Pattern Matching

### Match Method

Test if a path matches the pattern:

```ts theme={null}
const glob = new Glob("**/*.ts");

console.log(glob.match("src/index.ts")); // true
console.log(glob.match("src/index.js")); // false
console.log(glob.match("README.md")); // false
```

### Multiple Patterns

Match against multiple globs:

```ts theme={null}
const patterns = [
  new Glob("**/*.ts"),
  new Glob("**/*.tsx"),
  new Glob("!**/*.test.*"),
];

function matches(path: string): boolean {
  let result = false;
  
  for (const glob of patterns) {
    if (glob.pattern.startsWith("!")) {
      // Negation
      if (glob.match(path.slice(1))) {
        result = false;
      }
    } else {
      // Inclusion
      if (glob.match(path)) {
        result = true;
      }
    }
  }
  
  return result;
}

console.log(matches("src/index.ts")); // true
console.log(matches("src/index.test.ts")); // false
```

## Common Patterns

### All TypeScript Files

```ts theme={null}
const glob = new Glob("**/*.{ts,tsx}");
```

### All JavaScript Variants

```ts theme={null}
const glob = new Glob("**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}");
```

### Exclude node\_modules

```ts theme={null}
const glob = new Glob("**/*.js");

for await (const file of glob.scan(".")) {
  if (file.includes("node_modules")) continue;
  console.log(file);
}
```

Or use a function to filter:

```ts theme={null}
const files = [];
for await (const file of glob.scan(".")) {
  if (!file.includes("node_modules")) {
    files.push(file);
  }
}
```

### Specific Directories

```ts theme={null}
// Only src and test directories
const glob = new Glob("{src,test}/**/*.ts");

// Exclude build directories
const glob2 = new Glob("**/*.js");
for await (const file of glob2.scan(".")) {
  if (file.match(/\/(dist|build|out)\//)) continue;
  console.log(file);
}
```

### Test Files

```ts theme={null}
// Files ending in .test or .spec
const glob = new Glob("**/*.{test,spec}.{ts,js}");

// Files in __tests__ directory
const glob2 = new Glob("**/__tests__/**/*.{ts,js}");
```

### Config Files

```ts theme={null}
const glob = new Glob("*.config.{js,ts,json}");
// Matches: vite.config.js, tsconfig.json, etc.
```

## Performance

### Fast Scanning

Bun's glob is highly optimized:

```ts theme={null}
const glob = new Glob("**/*.js");

const start = performance.now();
let count = 0;
for await (const _ of glob.scan(".")) {
  count++;
}
console.log(`Found ${count} files in ${performance.now() - start}ms`);
// Typically <50ms for 10,000 files
```

### Comparison

* **Bun Glob**: \~200,000 files/sec
* **fast-glob**: \~100,000 files/sec
* **node-glob**: \~50,000 files/sec

### Optimization Tips

1. **Use specific patterns**
   ```ts theme={null}
   // Faster - specific directory
   const glob = new Glob("src/**/*.ts");

   // Slower - scans everything
   const glob2 = new Glob("**/*.ts");
   ```

2. **Filter early**
   ```ts theme={null}
   // Better - filter while scanning
   for await (const file of glob.scan(".")) {
     if (!file.includes("node_modules")) {
       process(file);
     }
   }

   // Worse - collect then filter
   const all = await Array.fromAsync(glob.scan("."));
   const filtered = all.filter(f => !f.includes("node_modules"));
   ```

3. **Use async iteration**
   ```ts theme={null}
   // Better - streams results
   for await (const file of glob.scan(".")) {
     process(file);
   }

   // Worse - buffers all in memory
   const files = await Array.fromAsync(glob.scan("."));
   files.forEach(process);
   ```

## Use Cases

### Build Tools

```ts theme={null}
import { Glob } from "bun";
import { build } from "./builder";

const glob = new Glob("src/**/*.ts");

for await (const file of glob.scan(".")) {
  await build(file);
}
```

### File Watching

```ts theme={null}
import { watch } from "fs";
import { Glob } from "bun";

const glob = new Glob("src/**/*.ts");

const watcher = watch("src", { recursive: true });

for await (const event of watcher) {
  if (glob.match(event.filename)) {
    console.log(`Changed: ${event.filename}`);
    // Rebuild...
  }
}
```

### Testing

```ts theme={null}
import { Glob } from "bun";

// Find all test files
const glob = new Glob("**/*.test.{ts,tsx}");
const testFiles = await Array.fromAsync(glob.scan("."));

// Run tests
for (const file of testFiles) {
  await import(file);
}
```

### Linting

```ts theme={null}
import { Glob } from "bun";
import { lint } from "./linter";

const glob = new Glob("**/*.{ts,tsx}");

for await (const file of glob.scan("src")) {
  const issues = await lint(file);
  if (issues.length > 0) {
    console.error(`${file}: ${issues.length} issues`);
  }
}
```

### Cleaning

```ts theme={null}
import { Glob } from "bun";
import { unlink } from "fs/promises";

// Remove all .js files
const glob = new Glob("**/*.js");

for await (const file of glob.scan("dist")) {
  await unlink(file);
}
```

## Advanced Usage

### Multiple Include/Exclude

```ts theme={null}
function createMatcher(include: string[], exclude: string[]) {
  const includeGlobs = include.map(p => new Glob(p));
  const excludeGlobs = exclude.map(p => new Glob(p));
  
  return (path: string) => {
    const included = includeGlobs.some(g => g.match(path));
    const excluded = excludeGlobs.some(g => g.match(path));
    return included && !excluded;
  };
}

const matches = createMatcher(
  ["**/*.ts", "**/*.tsx"],
  ["**/*.test.*", "**/node_modules/**"],
);

console.log(matches("src/index.ts")); // true
console.log(matches("src/index.test.ts")); // false
```

### Glob Expansion

Expand pattern to list of files:

```ts theme={null}
async function expand(pattern: string): Promise<string[]> {
  const glob = new Glob(pattern);
  return await Array.fromAsync(glob.scan("."));
}

const files = await expand("src/**/*.{ts,tsx}");
console.log(files);
```

### Custom Scanner

```ts theme={null}
import { Glob } from "bun";
import { stat } from "fs/promises";

class FilteredGlob {
  constructor(public pattern: string) {}
  
  async *scan(dir: string) {
    const glob = new Glob(this.pattern);
    
    for await (const file of glob.scan(dir)) {
      const stats = await stat(file);
      
      // Only files larger than 1KB
      if (stats.size > 1024) {
        yield file;
      }
    }
  }
}

const glob = new FilteredGlob("**/*.js");
for await (const file of glob.scan(".")) {
  console.log(file);
}
```

## Error Handling

```ts theme={null}
import { Glob } from "bun";

const glob = new Glob("**/*.ts");

try {
  for await (const file of glob.scan("/nonexistent")) {
    console.log(file);
  }
} catch (err) {
  if (err.code === "ENOENT") {
    console.error("Directory not found");
  } else {
    throw err;
  }
}
```

## Platform Support

Glob patterns work identically on:

* macOS
* Linux
* Windows (uses forward slashes internally)

### Windows Paths

```ts theme={null}
// Use forward slashes even on Windows
const glob = new Glob("src/**/*.js");

// Not backslashes
const wrong = new Glob("src\\**\\*.js"); // Wrong!
```
