Node.js Cheatsheet

File System (fs)

Use this Node.js reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Reading Files

import fs from "node:fs";
import { readFile } from "node:fs/promises";  // promise API (no sync fns here)
import { readFileSync } from "node:fs";       // sync API lives on node:fs

// Async (callback)
fs.readFile("file.txt", "utf8", (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Promise-based (recommended)
const data = await fs.promises.readFile("file.txt", "utf8");

// Sync (blocks event loop — avoid in servers)
const data = fs.readFileSync("file.txt", "utf8");

// As Buffer (no encoding)
const buf = await fs.promises.readFile("image.png");

Writing Files

// Overwrite (creates if missing)
await fs.promises.writeFile("out.txt", "hello\n", "utf8");
await fs.promises.writeFile("out.bin", buffer);

// Append
await fs.promises.appendFile("log.txt", "line\n");

// Write with options
await fs.promises.writeFile("out.txt", data, {
  encoding: "utf8",
  flag: "w",   // 'a' append, 'ax' append+exclusive, 'wx' write+exclusive
  mode: 0o644,
});

// Low-level (file descriptor)
const fd = await fs.promises.open("file.txt", "w");
await fd.write("data");
await fd.close();

File and Directory Info

const stat = await fs.promises.stat("file.txt");
stat.isFile();          // true
stat.isDirectory();     // false
stat.isSymbolicLink();  // false (use lstat for this)
stat.size;              // bytes
stat.mtime;             // Date — modified time
stat.atime;             // Date — access time
stat.ctime;             // Date — metadata change time
stat.birthtime;         // Date — creation time
stat.mode;              // file permission bits

// Does not follow symlinks
const lstat = await fs.promises.lstat("link");

// Check existence (prefer try/catch over access)
try {
  await fs.promises.access("file.txt", fs.constants.R_OK);
  // readable
} catch {
  // not readable or doesn't exist
}

Directory Operations

// List directory
const entries = await fs.promises.readdir("./src");           // string[]
const entries = await fs.promises.readdir("./src", { withFileTypes: true });
// entries[0].name, entries[0].isFile(), entries[0].isDirectory()

// Recursive list (Node 18.17+)
const all = await fs.promises.readdir("./src", { recursive: true });

// Create directory
await fs.promises.mkdir("new-dir");
await fs.promises.mkdir("a/b/c", { recursive: true });  // mkdir -p

// Remove directory (Node 14.14+)
await fs.promises.rm("dir", { recursive: true, force: true });

// Older alternative
await fs.promises.rmdir("empty-dir");

// Temp directory
const tmp = await fs.promises.mkdtemp("/tmp/prefix-");

Copying, Moving, Renaming, Deleting

// Copy file
await fs.promises.copyFile("src.txt", "dst.txt");
// COPYFILE_EXCL = fail if dst exists
await fs.promises.copyFile("src.txt", "dst.txt", fs.constants.COPYFILE_EXCL);

// Copy directory tree (Node 16.7+)
await fs.promises.cp("src/", "dst/", { recursive: true });

// Rename / move (same filesystem only)
await fs.promises.rename("old.txt", "new.txt");

// Delete file
await fs.promises.unlink("file.txt");

// Delete file or dir (Node 14.14+)
await fs.promises.rm("path", { recursive: true, force: true });

Watching Files

// Watch a file or directory for changes
const watcher = fs.watch("./src", { recursive: true }, (event, filename) => {
  console.log(event, filename);  // 'rename' | 'change'
});
watcher.close();

// Promise-based async iterator (Node 19.1+)
import { watch } from "node:fs/promises";
const ac = new AbortController();
for await (const { eventType, filename } of watch(".", { signal: ac.signal })) {
  console.log(eventType, filename);
}

File Descriptors and Low-Level I/O

// Open flags
"r"   // read; error if missing
"r+"  // read+write
"w"   // write; create/truncate
"wx"  // write; error if exists
"a"   // append; create if missing
"ax"  // append; error if exists

const fh = await fs.promises.open("file.txt", "r+");

// Read into buffer at offset
const buf = Buffer.alloc(100);
const { bytesRead } = await fh.read(buf, 0, 100, 0);

// Write buffer at position
await fh.write(buf, 0, bytesRead, 0);

// Flush to OS
await fh.datasync();   // data only
await fh.sync();       // data + metadata

await fh.truncate(1024);  // set file size

await fh.close();

Common Patterns

// Read JSON config
const config = JSON.parse(await fs.promises.readFile("config.json", "utf8"));

// Write JSON
await fs.promises.writeFile("out.json", JSON.stringify(data, null, 2));

// Process file line by line (memory-efficient)
import readline from "node:readline";
const rl = readline.createInterface({ input: fs.createReadStream("big.txt") });
for await (const line of rl) {
  console.log(line);
}

// Atomic write (write to tmp, then rename)
const tmp = "out.json.tmp";
await fs.promises.writeFile(tmp, JSON.stringify(data));
await fs.promises.rename(tmp, "out.json");

// Walk directory tree recursively (Node < 18.17)
async function* walk(dir) {
  for (const entry of await fs.promises.readdir(dir, { withFileTypes: true })) {
    const full = path.join(dir, entry.name);
    if (entry.isDirectory()) yield* walk(full);
    else yield full;
  }
}
for await (const file of walk("./src")) console.log(file);

fs.constants

ConstantUse
F_OKFile exists
R_OKReadable
W_OKWritable
X_OKExecutable
COPYFILE_EXCLcopyFile fails if dst exists
COPYFILE_FICLONEUse copy-on-write reflink if available
O_RDONLYOpen read-only
O_WRONLYOpen write-only
O_RDWROpen read-write
O_CREATCreate if missing
O_TRUNCTruncate on open
O_APPENDAppend mode
O_EXCLError if exists