Working with File System (fs)
1. Reading Files
Example: Promise API
import fs from "node:fs/promises";
const text = await fs.readFile("a.txt", "utf8");
const bytes = await fs.readFile("img.png"); // Buffer
| Variant | Use |
fs.readFile | Whole file into memory |
fs.createReadStream | Large files (streaming) |
fs.readFileSync | Sync (avoid in servers) |
2. Writing Files
| API | Behavior |
fs.writeFile(path, data) | Replace contents |
fs.writeFile(path, data, { flag: "wx" }) | Fail if exists |
fs.createWriteStream | Streaming writes |
3. Appending to Files (fs.appendFile)
Example
await fs.appendFile("audit.log", `${Date.now()} ${msg}\n`);
4. Checking File Existence
| Approach | Notes |
await fs.access(path) + try/catch | Idiomatic |
fs.existsSync(path) | Sync only |
fs.exists | DEPRECATED |
Warning: Don't check-then-use (race condition). Just attempt the operation and handle ENOENT.
5. Getting File Stats
| API | Returns |
fs.stat(path) | Stats (follows symlinks) |
fs.lstat(path) | Stats (no follow) |
stat.size / mtime / isFile() / isDirectory() | Common fields |
{ bigint: true } | Use BigInt for large nums |
6. Creating Directories
| API | Notes |
fs.mkdir(path) | Single dir |
fs.mkdir(path, { recursive: true }) | Like mkdir -p |
fs.mkdtemp(prefix) | Temp dir with random suffix |
7. Reading Directories
| API | Returns |
fs.readdir(p) | Array of names |
fs.readdir(p, { withFileTypes: true }) | Array of Dirent |
fs.readdir(p, { recursive: true }) | Walk tree v20+ |
fs.opendir(p) | Async iterable |
8. Deleting Files
| API | Use |
fs.unlink(p) | Delete file |
fs.rm(p) | File or directory |
9. Removing Directories
| API | Use |
fs.rmdir(p) | Empty dir |
fs.rm(p, { recursive: true, force: true }) | Recursive (preferred) |
10. Watching Files
Example
const ac = new AbortController();
const watcher = fs.watch("./src", { recursive: true, signal: ac.signal });
for await (const ev of watcher) console.log(ev.eventType, ev.filename);
| Event | Meaning |
change | Content modified |
rename | Created / removed / renamed |
Note: For reliable cross-platform watching, use chokidar.
11. Using Promises API (fs/promises)
| Import | Style |
import fs from "node:fs/promises" | Promise-based (preferred) |
import fs from "node:fs" | Callback + sync |
12. Working with File Descriptors
Example: FileHandle
const fh = await fs.open("data.bin", "r+");
try {
const { bytesRead } = await fh.read(buf, 0, 1024, 0);
await fh.write(out, 0, out.length, 0);
} finally { await fh.close(); }
| Flag | Mode |
r | Read |
r+ | Read/write |
w | Write (truncate) |
wx | Write (fail if exists) |
a | Append |
13. Copying Files (fs.copyFile)
| API | Use |
fs.copyFile(src, dest) | Single file |
fs.cp(src, dest, { recursive: true }) | Files or directories |
Flag COPYFILE_EXCL | Fail if dest exists |
14. Renaming Files (fs.rename)
| Note | Detail |
| Atomic on same filesystem | Cross-fs may fail |
| Works for files and dirs | Same call |
15. Creating Symlinks
| API | Use |
fs.symlink(target, path) | Create symlink |
fs.readlink(path) | Read target |
fs.realpath(path) | Resolve to absolute path |
| Type (Windows) | "file" / "dir" / "junction" |