Last updated

Working with filesystems in Node.js

Node's fs module gives you a great cross-platform toolkit for working with filesystems. With a few third-party modules it becomes everything you need

Estimated reading time: 3 minutes

Table of contents

Different ways to read a file

Node provides three different ways to read a file through the fs module.

To read a file synchronously you can do this

var data = fs.readFileSync('/path/to/some/file.txt','utf8');

To read a file asynchronously you can do this

fs.readFile('/path/to/some/file.txt', function (err, data) {
  if (err) throw err;

Finally to read a file as a stream you can do this

var readStream = fs.createReadStream('/path/to/some/file.txt');

The difference in these are fundamental to how node works. The synchronous read will halt your program until the read has finished. The asynchronous read lets your program get on with other things and makes the data available via the callback. Reading a file as a stream makes the data available as soon as chunks of it are ready and lets you pipe it through other streams too.

The fs module provides most things that you need. If you are a UNIX user the api should be familiar to you.

Just enough but missing some things

The fs module provides a good toolkit for working with the filesystem but some operations are missing. If you do anything moderately complex with the fs module you will realise that you will either have to start getting into nested callback operations or look to third party modules to help you out. Thankfully there are some excellent (and small) third-party modules available.


Rimraf provides an rm -rf for node. If there are times when you want to recursively delete files this is a tool that does one thing well.

rimraf('/some/folder', function(err) {
  if (err) { throw err; }
  // done


If you are a UNIX user you are probably used to doing mkdir -p /some/directory/path. This will create all the directories in the path if they don’t exist. If you are just using the fs module this is difficult to do but the mkdirp module comes to the rescue.

mkdirp('/some/directory/path', function (err) {
  if (err) { throw err; }
  // done


chomdr does what you would expect chmod -R or recursively changing file or folder permissions.

chmodr("/some/folder", 0777, function (err) {
  if (err) { throw err; }
  // done


chown recursively changes the ownership of files and folders like chown -R in UNIX.

chownr("/some/folder", 501, 20, function (err) {
  if (err) { throw err; }
  // done


Sooner or later you will want to do a recursive copy like cp -R in UNIX. This is tricky with the fs module but a module called ncp can help you achive that.

ncp('/dir/to/copy/from', '/dir/to/copy/to', function (err) {
  if (err) { throw err; }
  // done

Other tools

There are wealth of other tools available. Check npm for fs module extensions and other goodies. Personally I favour modules that do one thing well but there are a number of modules that extend the fs module with more methods if that is your kind of thing.


Node’s fs module gives you enough to work with filesystems and provides a single API to smooth out differences between operating systems. The third-party module ecosystem picks things up from there and plugs a few gaps to make node a very capable tool for working with filesystems. Personally I think it is great that more functionality isn’t shoved into core modules. Experience of standard libraries like Net:HTTP in Ruby suggest that core is where things go to rot and third-party libraries are often better anyway.

Have an update or suggestion for this article? You can edit it here and send me a pull request.


Recent Posts