Copy folder recursively in Node.js

前端 未结 25 1810
隐瞒了意图╮
隐瞒了意图╮ 2020-12-04 07:44

Is there an easier way to copy a folder and all its content without manually doing a sequence of fs.readir, fs.readfile, fs.writefile

相关标签:
25条回答
  • 2020-12-04 08:11

    It looks like ncp and wrench both are no longer maintained. Probably the best option is to use fs-extra

    The Developer of Wrench directs users to use fs-extra as he has deprecated his library

    copySync & moveSync both will copy and move folders even if they have files or subfolders and you can easily move or copy files using it

    const fse = require('fs-extra');
    
    const srcDir = `path/to/file`;
    const destDir = `path/to/destination/directory`;
    
    // To copy a folder or file
    fse.copySync(srcDir, destDir, function (err) {
      if (err) {
        console.error(err);
      } else {
        console.log("success!");
      }
    });
    

    OR

    // To move a folder or file 
    fse.moveSync(srcDir, destDir, function (err) {
      if (err) {
        console.error(err);
      } else {
        console.log("success!");
      }
    });
    
    0 讨论(0)
  • 2020-12-04 08:12

    I wrote this function for both copying (copyFileSync) or moving (renameSync) files recursively between directories:

    // Copy files
    copyDirectoryRecursiveSync(sourceDir, targetDir);
    // Move files
    copyDirectoryRecursiveSync(sourceDir, targetDir, true);
    
    
    function copyDirectoryRecursiveSync(source, target, move) {
        if (!fs.lstatSync(source).isDirectory())
            return;
    
        var operation = move ? fs.renameSync : fs.copyFileSync;
        fs.readdirSync(source).forEach(function (itemName) {
            var sourcePath = path.join(source, itemName);
            var targetPath = path.join(target, itemName);
    
            if (fs.lstatSync(sourcePath).isDirectory()) {
                fs.mkdirSync(targetPath);
                copyDirectoryRecursiveSync(sourcePath, targetDir);
            }
            else {
                operation(sourcePath, targetPath);
            }
        });
    }
    
    0 讨论(0)
  • 2020-12-04 08:13

    I tried fs-extra and copy-dir to copy-folder-recursively. but I want it to

    1. work normally (copy-dir throws an unreasonable error)
    2. provide two arguments in filter: filepath and filetype (fs-extra does't tell filetype)
    3. have a dir-to-subdir check and a dir-to-file check

    So I wrote my own:

    // Node.js module for Node.js 8.6+
    var path = require("path");
    var fs = require("fs");
    
    function copyDirSync(src, dest, options) {
      var srcPath = path.resolve(src);
      var destPath = path.resolve(dest);
      if(path.relative(srcPath, destPath).charAt(0) != ".")
        throw new Error("dest path must be out of src path");
      var settings = Object.assign(Object.create(copyDirSync.options), options);
      copyDirSync0(srcPath, destPath, settings);
      function copyDirSync0(srcPath, destPath, settings) {
        var files = fs.readdirSync(srcPath);
        if (!fs.existsSync(destPath)) {
          fs.mkdirSync(destPath);
        }else if(!fs.lstatSync(destPath).isDirectory()) {
          if(settings.overwrite)
            throw new Error(`Cannot overwrite non-directory '${destPath}' with directory '${srcPath}'.`);
          return;
        }
        files.forEach(function(filename) {
          var childSrcPath = path.join(srcPath, filename);
          var childDestPath = path.join(destPath, filename);
          var type = fs.lstatSync(childSrcPath).isDirectory() ? "directory" : "file";
          if(!settings.filter(childSrcPath, type))
            return;
          if (type == "directory") {
            copyDirSync0(childSrcPath, childDestPath, settings);
          } else {
            fs.copyFileSync(childSrcPath, childDestPath, settings.overwrite ? 0 : fs.constants.COPYFILE_EXCL);
            if(!settings.preserveFileDate)
              fs.futimesSync(childDestPath, Date.now(), Date.now());
          }
        });
      }
    }
    copyDirSync.options = {
      overwrite: true,
      preserveFileDate: true,
      filter: function(filepath, type) {
        return true;
      }
    };
    

    And a similar function, mkdirs, which is an alternative to mkdirp:

    function mkdirsSync(dest) {
      var destPath = path.resolve(dest);
      mkdirsSync0(destPath);
      function mkdirsSync0(destPath) {
        var parentPath = path.dirname(destPath);
        if(parentPath == destPath)
          throw new Error(`cannot mkdir ${destPath}, invalid root`);
        if (!fs.existsSync(destPath)) {
          mkdirsSync0(parentPath);
          fs.mkdirSync(destPath);
        }else if(!fs.lstatSync(destPath).isDirectory()) {
          throw new Error(`cannot mkdir ${destPath}, a file already exists there`);
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-04 08:14

    The fs-extra module works like a charm.

    Install fs-extra:

    $ npm install fs-extra
    

    The following is the program to copy a source directory to a destination directory.

    // Include the fs-extra package
    var fs = require("fs-extra");
    
    var source = 'folderA'
    var destination = 'folderB'
    
    // Copy the source folder to the destination
    fs.copy(source, destination, function (err) {
        if (err){
            console.log('An error occurred while copying the folder.')
            return console.error(err)
        }
        console.log('Copy completed!')
    });
    

    References

    fs-extra: https://www.npmjs.com/package/fs-extra

    Example: Node.js Tutorial - Node.js Copy a Folder

    0 讨论(0)
  • 2020-12-04 08:18

    I know so many answers are already here, but no one answered it in a simple way.

    Regarding fs-exra official documentation, you can do it very easy.

    const fs = require('fs-extra')
    
    // Copy file
    fs.copySync('/tmp/myfile', '/tmp/mynewfile')
    
    // Copy directory, even if it has subdirectories or files
    fs.copySync('/tmp/mydir', '/tmp/mynewdir')
    
    
    0 讨论(0)
  • 2020-12-04 08:20

    Mallikarjun M, thank you!

    fs-extra did the thing and it can even return a Promise if you do not provide a callback! :)

    const path = require('path')
    const fs = require('fs-extra')
    
    let source = path.resolve( __dirname, 'folderA')
    let destination = path.resolve( __dirname, 'folderB')
    
    fs.copy(source, destination)
      .then(() => console.log('Copy completed!'))
      .catch( err => {
        console.log('An error occurred while copying the folder.')
        return console.error(err)
      })
    
    0 讨论(0)
提交回复
热议问题