Mastering the filesystem in Node.js

Node prides itself for having a minimal core. Where some languages ship bindings for the full POSIX API, Node tries to ship the minimum amount of bindings required to provide full functionality and exposes it through a sync, async and stream api.

This approach means that there are some convenience functions that ship in the OS that must be recreated in Node. This is a pragmatic guide to staple Node filesystem packages.

Referencing files

When interacting with the filesystem it’s important to point to the right file. As npm packages are bundled into other repositories it’s important to use dynamic links, rather than hardcoding relationships. There are two staple patterns to make sure packages reference the right files:

Reading files

In Node the easiest way of asynchronously reading files is to use streams! Here’s an example:

Creating files

Creating files isn’t that much harder, here’s a Node implementation of the shell cat command:

Removing files

Removing files and directories is usually done with the shell rm -rf command. In Node this would be achieved using the rimraf package:

Creating directories

Creating directories is very similar to removing files using the mkdirp package:

Finding files

Find files in the current directory with readdirp:

Find a file in the current directory’s parent directories with findup:

Note on robustness

Though I’ve never used it, I’ve heard good things about graceful-fs. It has retries, queues and other goodies built in. Give it a shot if you run into filesystem issues.

Note on pipes

When piping lots of streams together it’s important to handle error events. Rather than doing .on(‘error’, cb) on each individual stream it’s recommended to use pump to handle errors and properly close streams.


Shout out to Titus Wormer (@wooorm) for proof reading.


You can reach me on @yoshuawuyts or yoshuawuyts [at] gmail.

Originally published at on September 20, 2015.