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

# File I/O

> Read and write files using Bun's optimized file I/O APIs, including BunFile, FileSink, and directory operations via node:fs.

<Note>
  `Bun.file` and `Bun.write` are heavily optimized and are the recommended way to perform file-system tasks in Bun. For operations not yet available natively—such as `mkdir` or `readdir`—use Bun's [nearly complete](/runtime/nodejs-compat#node-fs) implementation of [`node:fs`](https://nodejs.org/api/fs.html).
</Note>

## Reading files with `Bun.file()`

`Bun.file(path)` returns a `BunFile` instance — a lazily-loaded reference to a file on disk. The file is not read until you call a method on it.

```typescript theme={null}
const file = Bun.file("data.txt"); // relative to cwd
file.size;  // number of bytes
file.type;  // MIME type, e.g. "text/plain;charset=utf-8"
```

`BunFile` conforms to the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) interface. Read its contents in multiple formats:

<CodeGroup>
  ```typescript Read as text theme={null}
  const text = await Bun.file("data.txt").text();
  ```

  ```typescript Read as JSON theme={null}
  const data = await Bun.file("data.json").json();
  ```

  ```typescript Read as bytes theme={null}
  const bytes = await Bun.file("data.bin").bytes(); // Uint8Array
  ```

  ```typescript Read as ArrayBuffer theme={null}
  const buf = await Bun.file("data.bin").arrayBuffer();
  ```

  ```typescript Stream the file theme={null}
  const stream = Bun.file("data.txt").stream(); // ReadableStream
  ```
</CodeGroup>

### File references

You can create a `BunFile` using a path string, a file descriptor number, or a `file://` URL:

```typescript theme={null}
Bun.file("foo.txt");                    // relative to cwd
Bun.file("/absolute/path/to/foo.txt");  // absolute path
Bun.file(1234);                         // file descriptor number
Bun.file(new URL(import.meta.url));     // reference to the current file
```

### File metadata

```typescript theme={null}
const file = Bun.file("data.txt");

file.size;          // number of bytes (0 if file doesn't exist)
file.type;          // MIME type string
await file.exists(); // boolean — false if file doesn't exist
```

A `BunFile` can reference a path that doesn't exist yet. No error is thrown until you try to read it:

```typescript theme={null}
const ghost = Bun.file("missing.txt");
ghost.size;             // 0
ghost.type;             // "text/plain;charset=utf-8"
await ghost.exists();   // false
```

To override the inferred MIME type, pass a second argument:

```typescript theme={null}
const file = Bun.file("data.json", { type: "application/json" });
file.type; // "application/json;charset=utf-8"
```

### Standard I/O streams

Bun exposes `stdin`, `stdout`, and `stderr` as `BunFile` instances:

```typescript theme={null}
Bun.stdin;   // readonly
Bun.stdout;
Bun.stderr;
```

### Deleting files

```typescript theme={null}
await Bun.file("logs.json").delete();
```

***

## Writing files with `Bun.write()`

`Bun.write(destination, data)` writes data to disk and returns a `Promise<number>` (bytes written).

**Destination** can be a `string` path, `file://` URL, or `BunFile`. **Data** can be a `string`, `Blob`, `BunFile`, `ArrayBuffer`, `TypedArray`, or `Response`.

<CodeGroup>
  ```typescript Write a string theme={null}
  await Bun.write("output.txt", "Hello, world!");
  ```

  ```typescript Copy a file theme={null}
  const input = Bun.file("input.txt");
  const output = Bun.file("output.txt");
  await Bun.write(output, input);
  ```

  ```typescript Write a Uint8Array theme={null}
  const encoder = new TextEncoder();
  const data = encoder.encode("binary content");
  await Bun.write("output.bin", data);
  ```

  ```typescript Write an HTTP response body to disk theme={null}
  const response = await fetch("https://example.com");
  await Bun.write("index.html", response);
  ```

  ```typescript Write to stdout theme={null}
  await Bun.write(Bun.stdout, Bun.file("input.txt"));
  ```
</CodeGroup>

Bun automatically selects the fastest available system call for each input/output combination (e.g., `copy_file_range` on Linux, `clonefile` on macOS).

***

## Incremental writing with `FileSink`

For streaming or incremental writes, use `FileSink` — Bun's native incremental file writer.

### Basic usage

```typescript theme={null}
const file = Bun.file("output.txt");
const writer = file.writer();

writer.write("first chunk\n");
writer.write("second chunk\n");

writer.flush(); // flush buffer to disk
writer.end();   // flush and close
```

### High water mark

Control when the buffer auto-flushes by setting a `highWaterMark`:

```typescript theme={null}
const writer = Bun.file("output.txt").writer({
  highWaterMark: 1024 * 1024, // flush after 1 MB
});
```

### Process lifetime

By default, the Bun process stays alive until `FileSink` is closed. Opt out with `.unref()`:

```typescript theme={null}
writer.unref(); // process won't wait for this sink
writer.ref();   // re-attach if needed
```

***

## Module path helpers

Bun provides module-relative path helpers on `import.meta`:

```typescript theme={null}
import.meta.dir;   // absolute path to the directory of the current file
import.meta.file;  // filename of the current file (e.g. "index.ts")
import.meta.path;  // absolute path to the current file
```

These are useful for constructing paths relative to the current source file:

```typescript theme={null}
const configPath = import.meta.dir + "/config.json";
const config = await Bun.file(configPath).json();
```

***

## Directory operations

Bun does not yet have a native directory API. Use `node:fs` instead.

<CodeGroup>
  ```typescript Read a directory theme={null}
  import { readdir } from "node:fs/promises";

  const files = await readdir(import.meta.dir);
  ```

  ```typescript Read recursively theme={null}
  import { readdir } from "node:fs/promises";

  const files = await readdir("./src", { recursive: true });
  ```

  ```typescript Create a directory theme={null}
  import { mkdir } from "node:fs/promises";

  await mkdir("path/to/dir", { recursive: true });
  ```
</CodeGroup>

***

## API reference

```typescript theme={null}
interface Bun {
  stdin: BunFile;
  stdout: BunFile;
  stderr: BunFile;

  file(path: string | number | URL, options?: { type?: string }): BunFile;

  write(
    destination: string | number | BunFile | URL,
    input:
      | string
      | Blob
      | ArrayBuffer
      | SharedArrayBuffer
      | TypedArray
      | Response,
  ): Promise<number>;
}

interface BunFile extends Blob {
  readonly size: number;
  readonly type: string;

  text(): Promise<string>;
  json(): Promise<any>;
  bytes(): Promise<Uint8Array>;
  arrayBuffer(): Promise<ArrayBuffer>;
  stream(): ReadableStream;
  exists(): Promise<boolean>;
  delete(): Promise<void>;
  writer(params?: { highWaterMark?: number }): FileSink;
}

interface FileSink {
  write(
    chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer,
  ): number;
  flush(): number | Promise<number>;
  end(error?: Error): number | Promise<number>;
  ref(): void;
  unref(): void;
}
```

## Glob

`Bun.Glob` provides fast native file globbing. Use it to scan directories or match strings against patterns.

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

// Scan a directory for all TypeScript files
const glob = new Glob("**/*.ts");

for await (const file of glob.scan(".")) {
  console.log(file); // "src/index.ts", "src/utils/helpers.ts", ...
}
```

**Match a string against a pattern:**

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

glob.match("index.ts");   // true
glob.match("index.js");   // false
glob.match("App.tsx");    // true
```

**Scan options:**

```typescript theme={null}
for await (const file of glob.scan({
  cwd: "./src",        // root directory (default: process.cwd())
  dot: true,           // include dotfiles
  absolute: true,      // return absolute paths
  onlyFiles: true,     // exclude directories (default: true)
})) {
  console.log(file);
}
```

**Synchronous scan:**

```typescript theme={null}
const files = [...glob.scanSync("./src")];
```

Supported glob syntax: `*`, `**`, `?`, `[abc]`, `{a,b}`, and negation with `!`.
