是否有一种更简单的方法来复制文件夹及其所有内容,而无需手动执行一系列的fs。readir, fs。readfile, fs。writefile递归?

我只是想知道我是否错过了一个函数,理想情况下是这样工作的:

fs.copy("/path/to/source/folder", "/path/to/destination/folder");

关于这个历史问题。注意fs。Cp和fs。cpSync可以递归复制文件夹,在Node v16+中可用


当前回答

内联版本

node -e "const fs=require('fs');const p=require('path');function copy(src, dest) {if (!fs.existsSync(src)) {return;} if (fs.statSync(src).isFile()) {fs.copyFileSync(src, dest);}else{fs.mkdirSync(dest, {recursive: true});fs.readdirSync(src).forEach(f=>copy(p.join(src, f), p.join(dest, f)));}}const args=Array.from(process.argv); copy(args[args.length-2], args[args.length-1]);" dist temp\dest

或者节点16.x+

node -e "const fs=require('fs');const args=Array.from(process.argv); fs.cpSync(args[args.length-2], args[args.length-1], {recursive: true});" 

在“节点14.20.0”上测试,但假设它在节点10.x上工作?

来自user8894303和pen的回答:https://stackoverflow.com/a/52338335/458321

如果在包中使用,请务必转义引号。json脚本

package.json:

  "scripts": {
    "rmrf": "node -e \"const fs=require('fs/promises');const args=Array.from(process.argv); Promise.allSettled(args.map(a => fs.rm(a, { recursive: true, force: true })));\"",
    "cp": "node -e \"const fs=require('fs');const args=Array.from(process.argv);if (args.length>2){ fs.cpSync(args[args.length-2], args[args.length-1], {recursive: true});}else{console.log('args missing', args);}\""
    "copy": "node -e \"const fs=require('fs');const p=require('path');function copy(src, dest) {if (!fs.existsSync(src)) {return;} if (fs.statSync(src).isFile()) {fs.copyFileSync(src, dest);}else{fs.mkdirSync(dest, {recursive: true});fs.readdirSync(src).forEach(f=>copy(p.join(src, f), p.join(dest, f)));}}const args=Array.from(process.argv);if (args.length>2){copy(args[args.length-2], args[args.length-1]);}else{console.log('args missing', args);}\"",
    "mkdir": "node -e \"const fs=require('fs');const args=Array.from(process.argv);fs.mkdirSync(args[args.length-1],{recursive:true});\"",
    "clean": "npm run rmrf -- temp && npm run mkdir -- temp && npm run copy -- dist temp"
  }

注:RMRF脚本需要14.20节点。X还是12.20.x?

奖金:

deno eval "import { existsSync, mkdirSync, copyFileSync, readdirSync, statSync } from 'node:fs';import { join } from 'node:path';function copy(src, dest) {if (!existsSync(src)) {return;} if (statSync(src).isFile()) {copyFileSync(src, dest);}else{mkdirSync(dest, {recursive: true});readdirSync(src).forEach(f=>copy(join(src, f), join(dest, f)));}}const args=Array.from(Deno.args);copy(args[0], args[1]);" dist temp\dest -- --allow-read --allow-write

Deno支持-> NPM I Deno -bin支持节点中的Deno -bin

其他回答

Mallikarjun M,谢谢!

fs-extra做了这件事,如果你不提供一个回调,它甚至可以返回一个承诺!:)

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)
  })

从Node v16.7.0开始:

import { cp } from 'fs/promises';
await cp(
  new URL('../path/to/src/', import.meta.url),
  new URL('../path/to/dest/', import.meta.url), {
    recursive: true,
  }
);

注意使用递归:true。这可以防止ERR_FS_EISDIR错误。

阅读更多关于节点文件系统的文档

使用 shelljs

npm i -D shelljs

const bash = require('shelljs');
bash.cp("-rf", "/path/to/source/folder", "/path/to/destination/folder");

我尝试了fs-extra和copy-dir来递归地复制文件夹。但我希望它能

正常工作(copy-dir抛出一个不合理的错误) 在过滤器中提供两个参数:filepath和filetype (fs-extra不告诉文件类型) 有从目录到子目录的检查和从目录到文件的检查吗

所以我自己写了:

// 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;
  }
};

还有一个类似的函数mkdirs,它是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`);
    }
  }
}

我创建了一个小的工作示例,只需几个步骤就可以将源文件夹复制到另一个目标文件夹(基于shift66使用ncp的答案):

步骤1 -安装ncp模块:

npm install ncp --save

步骤2 -创建copy.js(修改srcPath和destPath变量为你需要的任何变量):

var path = require('path');
var ncp = require('ncp').ncp;

ncp.limit = 16;

var srcPath = path.dirname(require.main.filename); // Current folder
var destPath = '/path/to/destination/folder'; // Any destination folder

console.log('Copying files...');
ncp(srcPath, destPath, function (err) {
  if (err) {
    return console.error(err);
  }
  console.log('Copying files complete.');
});

第三步——跑步

node copy.js