Node.js Files and Paths Cheat Sheet
Your pocket guide to files and paths in Node.js: read, write, list, copy, stream, and watch with the modern promise-based APIs. You can also download the information as a printable cheat sheet:
Free Bonus: Node.js Files and Paths Cheat Sheet
Get the Node.js Files and Paths Cheat Sheet (PDF), a printable reference to paths with node:path, reading and writing text and JSON, listing and globbing, copying and deleting, file metadata, streams and pipeline, watch mode, and --env-file:
Want a guided path instead of a reference? Start learning at realjs.com.
Paths With node:path
- Use
join()andresolve(), never string concatenation - A path is just a string until you touch the disk
resolve()returns an absolute path
Build and Inspect a Path
import path from "node:path";
const p = path.join("reports", "a.csv");
p; // 'reports/a.csv'
path.basename(p); // 'a.csv'
path.extname(p); // '.csv'
path.dirname(p); // 'reports'
path.resolve("a"); // '/home/me/a'
path.parse(p);
// { root: '', dir: 'reports',
// base: 'a.csv', ext: '.csv',
// name: 'a' }
Paths Relative to This File
const dir = import.meta.dirname;
// '/home/me/project'
const file = import.meta.filename;
// '/home/me/project/app.mjs'
const data = path.join(dir, "data.json");
Reading and Writing
- Pass
"utf8"or you get aBuffer writeFileoverwrites. UseappendFileto add- Import from
node:fs/promisesandawaitit
Read and Write Text
import {
readFile, writeFile, appendFile,
} from "node:fs/promises";
await writeFile("todo.txt", "Buy milk\n");
await appendFile("todo.txt", "Walk dog\n");
await readFile("todo.txt", "utf8");
// 'Buy milk\nWalk dog\n'
await readFile("todo.txt");
// <Buffer 42 75 79 ...>
Read and Write JSON
const cfg = { name: "demo", tags: ["a"] };
await writeFile(
"cfg.json",
JSON.stringify(cfg, null, 2) + "\n",
);
JSON.parse(
await readFile("cfg.json", "utf8"),
);
// { name: 'demo', tags: [ 'a' ] }
Never Overwrite by Accident
try {
await writeFile("a.txt", "x", {
flag: "wx",
});
} catch (err) {
console.log(err.code); // EEXIST
}
Listing and Globbing
fs.globis stable since Node 24 (and 22.17)- It returns an async iterator, not an array
readdirorder isn’t guaranteed. Sort it
List a Folder
import { readdir } from "node:fs/promises";
await readdir("reports");
// [ '2026', 'notes.txt' ]
const all = await readdir("reports", {
recursive: true,
});
// [ '2026', 'notes.txt', '2026/a.csv' ]
Tell Files From Folders
const items = await readdir("reports", {
withFileTypes: true,
});
for (const d of items) {
console.log(d.name, d.isDirectory());
}
// 2026 true
// notes.txt false
Match Patterns With glob
import { glob } from "node:fs/promises";
for await (const f of glob("src/**/*.js")) {
console.log(f); // src/lib/b.js
}
await Array.fromAsync(glob("*.json"));
// [ 'cfg.json' ]
Create, Copy, Move, Delete
- Deletion skips the recycle bin: there’s no undo
recursive: trueonmkdirismkdir -prenamecan silently replace the target
Create Nested Folders
import { mkdir } from "node:fs/promises";
await mkdir("a/b/c", { recursive: true });
Make a Temp Folder
import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
const tmp = await mkdtemp(
path.join(tmpdir(), "app-"),
);
// '/tmp/app-AIFcnT'
Copy, Move, and Rename
import {
cp, rename,
} from "node:fs/promises";
await cp("src", "backup", {
recursive: true,
});
await rename("old.txt", "archive/new.txt");
Delete
import { rm } from "node:fs/promises";
await rm("old.txt", { force: true });
await rm("build", {
recursive: true,
force: true, // Whole tree!
});
await rm("src"); // ERR_FS_EISDIR
Free Bonus: Download the Node.js Files and Paths Cheat Sheet PDF and keep the essentials at hand.
File Metadata
statrejects withENOENTif nothing is theresizeis in bytes.mtimeis aDate
Size, Type, and Modified Time
import { stat } from "node:fs/promises";
const info = await stat("cfg.json");
info.size; // 46
info.isFile(); // true
info.isDirectory(); // false
info.mtime.toISOString();
// '2026-01-15T09:30:00.000Z'
Check If It Exists
try {
await stat("nope.txt");
} catch (err) {
if (err.code !== "ENOENT") throw err;
console.log("Missing"); // Missing
}
Large Files and Streams
readFileloads everything into memory- Streams process one chunk at a time
- Use
pipelineso errors close every stream
Read Line by Line
import { open } from "node:fs/promises";
const fh = await open("todo.txt");
for await (const line of fh.readLines()) {
console.log(line);
}
// Buy milk
// Walk dog
Compress a File With pipeline
import {
createReadStream, createWriteStream,
} from "node:fs";
import { createGzip } from "node:zlib";
import {
pipeline,
} from "node:stream/promises";
await pipeline(
createReadStream("big.log"),
createGzip(),
createWriteStream("big.log.gz"),
);
Watching and Running
node --watchrestarts your script on changes--env-fileloadsKEY=valuelines intoprocess.env- File watchers can fire several events per save
Watch a Folder
import { watch } from "node:fs/promises";
const ac = new AbortController();
for await (const ev of watch("src", {
signal: ac.signal,
})) {
console.log(ev.eventType, ev.filename);
}
// change a.js
Restart on Changes
$ node --watch app.js
Restarting 'app.js'
$ node --watch-path=src app.js
Load a .env File
$ echo "API_KEY=abc" > .env
$ node --env-file=.env app.js
$ node --env-file-if-exists=.env app.js
process.env.API_KEY; // 'abc'
Want to go deeper on Node.js?
RealJS teaches the mental models that let you write, read, and review modern JavaScript with confidence, whether you or an AI wrote it.
Learn more at realjs.com 💡
You can download this information as a printable cheat sheet:
Free Bonus: Node.js Files and Paths Cheat Sheet
Get the Node.js Files and Paths Cheat Sheet (PDF), a printable reference to paths with node:path, reading and writing text and JSON, listing and globbing, copying and deleting, file metadata, streams and pipeline, watch mode, and --env-file: