y. lu
y. lu

Reputation: 361

Node fs copy a folder

I am trying to copy a folder using Node fs module. I am familiar with readFileSync() and writeFileSync() methods but I am wondering what method I should use to copy a specified folder?

Upvotes: 36

Views: 32269

Answers (7)

Robin Métral
Robin Métral

Reputation: 3208

Node 16.7.0 added experimental support for fs.cp and fs.cpSync:

(A)synchronously copies the entire directory structure from src to dest, including subdirectories and files.

The APIs became stable in Node.js 22.3.0.

// asynchronous
fs.cp(src, dest, { recursive: true }, (err) => {/* callback */});

// synchronous
fs.cpSync(src, dest, { recursive: true });

Upvotes: 0

KyleMit
KyleMit

Reputation: 30267

Save yourself the extra dependency with just 10 lines of native node functions

Add the following copyDir function:

const { promises: fs } = require("fs")
const path = require("path")

async function copyDir(src, dest) {
    let entries = await fs.readdir(src, { recursive: true, withFileTypes: true })

    for (let entry of entries) {
        let srcPath = path.join(entry.path, entry.name);
        let destPath = srcPath.replace(src, dest);
        let destDir = path.dirname(destPath);
        
        if (entry.isFile()) {
            await fs.mkdir(destDir, { recursive: true })
            await fs.copyFile(srcPath, destPath);
        }
    }
}

And then use like this:

copyDir("./inputFolder", "./outputFolder")

With recursive readdir as of v20.1.0, v18.17.0 (May 2023+). See previous revision if not updated yet.

Further Reading

Upvotes: 36

user3248186
user3248186

Reputation: 1558

You can use fs-extra to copy contents of one folder to another like this

var fs = require("fs-extra");

fs.copy('/path/to/source', '/path/to/destination', function (err) {
  if (err) return console.error(err)
  console.log('success!')
});

There's also a synchronous version.

fs.copySync('/path/to/source', '/path/to/destination')

Upvotes: 39

Anders
Anders

Reputation: 49

I liked KyleMit's answer, but thought a parallel version would be preferable.

The code is in TypeScript. If you need JavaScript, just delete the : string type annotations on the line of the declaration of copyDirectory.

import { promises as fs } from "fs"
import path from "path"

export const copyDirectory = async (src: string, dest: string) => {
  const [entries] = await Promise.all([
    fs.readdir(src, { withFileTypes: true }),
    fs.mkdir(dest, { recursive: true }),
  ])

  await Promise.all(
    entries.map((entry) => {
      const srcPath = path.join(src, entry.name)
      const destPath = path.join(dest, entry.name)
      return entry.isDirectory()
        ? copyDirectory(srcPath, destPath)
        : fs.copyFile(srcPath, destPath)
    })
  )
}

Upvotes: 3

Eonasdan
Eonasdan

Reputation: 7765

Here's the synchronous version of @KyleMit answer

copyDirectory(source, destination) {
    fs.mkdirSync(destination, { recursive: true });
    
    fs.readdirSync(source, { withFileTypes: true }).forEach((entry) => {
      let sourcePath = path.join(source, entry.name);
      let destinationPath = path.join(destination, entry.name);

      entry.isDirectory()
        ? copyDirectory(sourcePath, destinationPath)
        : fs.copyFileSync(sourcePath, destinationPath);
    });
  }

Upvotes: 3

Stanislav Potemkin
Stanislav Potemkin

Reputation: 11

There is an elegant syntax. You can use the pwd-fs module.

const FileSystem = require('pwd-fs');
const pfs = new FileSystem();

async () => {
  await pfs.copy('./path', './dest');
}

Upvotes: 0

fdrobidoux
fdrobidoux

Reputation: 295

You might want to check out the ncp package. It does exactly what you're trying to do; Recursively copy files from a path to another.

Here's something to get your started :

const fs = require("fs");
const path = require("path");
const ncp = require("ncp").ncp;
// No limit, because why not?
ncp.limit = 0;

var thePath = "./";
var folder = "testFolder";
var newFolder = "newTestFolder";

ncp(path.join(thePath, folder), path.join(thePath, newFolder), function (err) {
    if (err) {
        return console.error(err);
    }
    console.log("Done !");
});

Upvotes: 5

Related Questions