Node.js Recursive Copy RFC

Summary

Add recursive directory copying to the Node.js fs module.

Motivation

Recursively copying a directory is a common task and this currently requires using a third-party library. One of the goals of the Tooling Working Group is to add recursive functionality to the fs module. For example, we recently added an rm command that allows you to recursively remove a directory.

Detailed Explanation

Add a new method to the fs module named cp. This method will work similarly to the UNIX cp command and will initially provide a recursive option. We may add some additional options from the cp command if they make sense to include in Node.js.

Rationale and Alternatives

Continue requiring a third-party library

We could do nothing and continue to leave this functionality up to third-party libraries. Some drawbacks to this include having to require a third-party library as well as having to choose from the available third-party libraries.

Add a recursive option to the fs.copyFile command

We initially implemented recursive directory removal in a simiar way by adding it to the fs.rmdir command. We ended up moving this into a new fs.rm method since the UNIX version of rmdir does not delete files so this API was a bit confusing. We had to deprecate recursive rmdir in Node 15, however it might never be feasible to remove it entirely. We would like to avoid making the same mistakes again.

Implementation

We need to decide if we want to copy a recursive copy implementation from one of the existing libraries or if we'd rather make our own.

Prior Art

Third-party libraries

There are a number of third-party libraries that include this functioanlity, including:

  1. fs-extra repo
  2. recursive-copy repo
  3. fs-jetpack repo

Unresolved Questions and Bikeshedding

  1. Should we use an existing implementation or create our own?
  2. What other flags from the cp command should we include?
  3. What exactly should the behaviour be with the various combinations of flags when copying a file vs. a directory or in cases where the target already exists?
  4. cp behaves differently if the source path ends with a /, is that something we want?
  5. Do we want any special symlink handling?
  6. cp -n doesn't overwrite an existing target
  7. cp -f will delete and recreate files it can't open
Select a repo