Copy folder recursively in Node.js

前端 未结 25 1943
隐瞒了意图╮
隐瞒了意图╮ 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: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`);
        }
      }
    }
    

提交回复
热议问题