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

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

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

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


当前回答

下面是一个递归复制目录及其内容到另一个目录的函数:

const fs = require("fs")
const path = require("path")

/**
 * Look ma, it's cp -R.
 * @param {string} src  The path to the thing to copy.
 * @param {string} dest The path to the new copy.
 */
var copyRecursiveSync = function(src, dest) {
  var exists = fs.existsSync(src);
  var stats = exists && fs.statSync(src);
  var isDirectory = exists && stats.isDirectory();
  if (isDirectory) {
    fs.mkdirSync(dest);
    fs.readdirSync(src).forEach(function(childItemName) {
      copyRecursiveSync(path.join(src, childItemName),
                        path.join(dest, childItemName));
    });
  } else {
    fs.copyFileSync(src, dest);
  }
};

其他回答

下面是一个递归复制目录及其内容到另一个目录的函数:

const fs = require("fs")
const path = require("path")

/**
 * Look ma, it's cp -R.
 * @param {string} src  The path to the thing to copy.
 * @param {string} dest The path to the new copy.
 */
var copyRecursiveSync = function(src, dest) {
  var exists = fs.existsSync(src);
  var stats = exists && fs.statSync(src);
  var isDirectory = exists && stats.isDirectory();
  if (isDirectory) {
    fs.mkdirSync(dest);
    fs.readdirSync(src).forEach(function(childItemName) {
      copyRecursiveSync(path.join(src, childItemName),
                        path.join(dest, childItemName));
    });
  } else {
    fs.copyFileSync(src, dest);
  }
};

这在Node.js 10中非常简单:

const Path = require('path');
const FSP = require('fs').promises;

async function copyDir(src,dest) {
    const entries = await FSP.readdir(src, {withFileTypes: true});
    await FSP.mkdir(dest);
    for(let entry of entries) {
        const srcPath = Path.join(src, entry.name);
        const destPath = Path.join(dest, entry.name);
        if(entry.isDirectory()) {
            await copyDir(srcPath, destPath);
        } else {
            await FSP.copyFile(srcPath, destPath);
        }
    }
}

这里假设dest不存在。

从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错误。

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

由于我只是构建一个简单的Node.js脚本,我不希望脚本的用户需要导入一堆外部模块和依赖项,所以我开始思考,并从Bash shell中搜索运行命令。

这个Node.js代码片段递归地复制了一个名为node-webkit的文件夹。应用程序到一个名为build的文件夹:

child = exec("cp -r node-webkit.app build", function(error, stdout, stderr) {
    sys.print("stdout: " + stdout);
    sys.print("stderr: " + stderr);
    if(error !== null) {
        console.log("exec error: " + error);
    } else {

    }
});

感谢dzone的兰斯·波拉德让我开始。

上面的代码片段仅限于基于unix的平台,如macOS和Linux,但类似的技术也适用于Windows。

我是这样做的:

let fs = require('fs');
let path = require('path');

然后:

let filePath = // Your file path

let fileList = []
    var walkSync = function(filePath, filelist)
    {
        let files = fs.readdirSync(filePath);
        filelist = filelist || [];
        files.forEach(function(file)
        {
            if (fs.statSync(path.join(filePath, file)).isDirectory())
            {
                filelist = walkSync(path.join(filePath, file), filelist);
            }
            else
            {
                filelist.push(path.join(filePath, file));
            }
        });

        // Ignore hidden files
        filelist = filelist.filter(item => !(/(^|\/)\.[^\/\.]/g).test(item));

        return filelist;
    };

然后调用该方法:

This.walkSync(filePath, fileList)