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

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

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

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


当前回答

这是我个人的做法:

function copyFolderSync(from, to) {
    fs.mkdirSync(to);
    fs.readdirSync(from).forEach(element => {
        if (fs.lstatSync(path.join(from, element)).isFile()) {
            fs.copyFileSync(path.join(from, element), path.join(to, element));
        } else {
            copyFolderSync(path.join(from, element), path.join(to, element));
        }
    });
}

它适用于文件夹和文件。

其他回答

内联版本

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

我创建了一个小的工作示例,只需几个步骤就可以将源文件夹复制到另一个目标文件夹(基于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

打印稿版本

async function copyDir(source: string, destination: string): Promise<any> {
  const directoryEntries = await readdir(source, { withFileTypes: true });
  await mkdir(destination, { recursive: true });

  return Promise.all(
    directoryEntries.map(async (entry) => {
      const sourcePath = path.join(source, entry.name);
      const destinationPath = path.join(destination, entry.name);

      return entry.isDirectory()
        ? copyDir(sourcePath, destinationPath)
        : copyFile(sourcePath, destinationPath);
    })
  );
}

看起来ncp和扳手都不再维护了。可能最好的选择是使用fs-extra

扳手的开发人员指导用户使用fs-extra,因为他已经弃用了他的库

copySync和moveSync都将复制和移动文件夹,即使他们有文件或子文件夹,你可以很容易地移动或复制文件使用它

const fse = require('fs-extra');

const srcDir = `path/to/file`;
const destDir = `path/to/destination/directory`;
                                 
// To copy a folder or file, select overwrite accordingly
try {
  fs.copySync(srcDir, destDir, { overwrite: true|false })
  console.log('success!')
} catch (err) {
  console.error(err)
}

OR

// To Move a folder or file, select overwrite accordingly
try {
  fs.moveSync(srcDir, destDir, { overwrite: true|false })
  console.log('success!')
} catch (err) {
  console.error(err)
}

我尝试了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`);
    }
  }
}