【问题标题】:Copy folder recursively in Node.js在 Node.js 中递归复制文件夹
【发布时间】:2012-11-26 23:50:24
【问题描述】:

有没有一种更简单的方法来复制文件夹及其所有内容,而无需手动递归地执行fs.readirfs.readfilefs.writefile 的序列?

我只是想知道我是否缺少一个理想情况下可以像这样工作的函数:

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

【问题讨论】:

  • 有没有办法在没有任何模块的情况下做到这一点?也许是一个递归函数/代码snip-it?
  • @Sukima - 查看我的回答 here
  • “没有手动”和没有模块是什么意思?您是要本机 bash 命令还是任何 Nodejs 内置库?如果是的话,还没有这样的事情。选项是重新发明轮子并创建递归函数或使用第三方轮子

标签: javascript node.js fs


【解决方案1】:

有些模块支持复制文件夹及其内容。最受欢迎的是wrench.js

// Deep-copy an existing directory
wrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up');

另一种选择是node-fs-extra:

fs.copy('/tmp/mydir', '/tmp/mynewdir', function (err) {
  if (err) {
    console.error(err);
  } else {
    console.log("success!");
  }
}); // Copies directory, even if it has subdirectories or files

【讨论】:

  • 如果要复制的目录包含符号链接,扳手将失败
  • 如果目录已经存在,它也会在 Windows 上失败,ncp 直接工作。
  • node-fs-extra 为我工作。它继承了原始 fs,我喜欢它处理该过程的方式。在应用中更新的代码更少。
  • 请注意wrench 已被弃用,应替换为node-fs-extra (github.com/jprichardson/node-fs-extra)
  • Wrench 实际上并不复制文件。它读取它们然后写入它们,然后复制它们的日期。那不是抄袭。复制包括 Windows 和 MacOS 都支持的其他元数据流,并且不会被扳手复制。
【解决方案2】:

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

此 Node.js 代码 sn-p 递归地将名为 node-webkit.app 的文件夹复制到名为 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 {

    }
});

感谢 Lance Pollard at dzone 让我开始。

上述 sn-p 仅限于基于 Unix 的平台,如 macOS 和 Linux,但类似的技术可能适用于 Windows。

【讨论】:

【解决方案3】:

这是一个递归地将目录及其内容复制到另一个目录的函数:

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

【讨论】:

  • 即使你要插入一个真正的复制功能,你也不应该跟随符号链接(使用fs.lstatSync而不是fs.statSync
  • 可能造成这种混乱的是 fs.unlink 删除文件,但 fs.link 不是复制而是链接。
  • @SimonSeyock: 是对的.. 是linking 没有复制.. 问题是当你修改链接文件的内容时,原始文件也会改变。
【解决方案4】:

这是我在没有任何额外模块的情况下解决此问题的方法。只需使用内置的fspath 模块。

注意:这确实使用了fs的读/写功能,所以它不会复制任何元数据(创建时间等)。从 Node.js 8.5 开始,有一个 copyFileSync 函数可用,它调用操作系统复制函数,因此也复制元数据。我还没有测试它们,但它应该可以替换它们。 (见https://nodejs.org/api/fs.html#fs_fs_copyfilesync_src_dest_flags

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

function copyFileSync( source, target ) {

    var targetFile = target;

    // If target is a directory, a new file with the same name will be created
    if ( fs.existsSync( target ) ) {
        if ( fs.lstatSync( target ).isDirectory() ) {
            targetFile = path.join( target, path.basename( source ) );
        }
    }

    fs.writeFileSync(targetFile, fs.readFileSync(source));
}

function copyFolderRecursiveSync( source, target ) {
    var files = [];

    // Check if folder needs to be created or integrated
    var targetFolder = path.join( target, path.basename( source ) );
    if ( !fs.existsSync( targetFolder ) ) {
        fs.mkdirSync( targetFolder );
    }

    // Copy
    if ( fs.lstatSync( source ).isDirectory() ) {
        files = fs.readdirSync( source );
        files.forEach( function ( file ) {
            var curSource = path.join( source, file );
            if ( fs.lstatSync( curSource ).isDirectory() ) {
                copyFolderRecursiveSync( curSource, targetFolder );
            } else {
                copyFileSync( curSource, targetFolder );
            }
        } );
    }
}

【讨论】:

  • 如果文件夹名称中有空格,它不会复制文件夹
  • 对我来说,它确实会复制名称中带有空格的文件夹。可能是由@victor 纠正的错误引起的。由于我经常使用此功能(在当前状态下,因为我忘记更新相同的修正 victor 所做的),我很确定它在一般情况下确实有效。
  • 还需要:javascript var fs = require('fs'); var path = require('path');
  • 这实际上并不复制文件。它读取它们然后写入它们。那不是抄袭。复制包括创建日期以及 Windows 和 MacOS 都支持且不被此代码复制的其他元数据流。从节点 8.5 开始,您应该调用 fs.copyfs.copySync,因为它们实际调用 MacOS 和 Windows 中的操作系统级复制函数,因此实际上是复制文件。
  • 对不起,它是fs.copyFile,如果你挖掘节点源代码,你会在 Mac 和 Windows 上看到它们调用操作系统特定的函数来复制文件
【解决方案5】:

这段代码可以正常工作,递归地将任何文件夹复制到任何位置。但它只是 Windows。

var child = require("child_process");
function copySync(from, to){
    from = from.replace(/\//gim, "\\");
    to = to.replace(/\//gim, "\\");
    child.exec("xcopy /y /q \"" + from + "\\*\" \"" + to + "\\\"");
}

它非常适合用于创建新玩家的基于文本的游戏。

【讨论】:

    【解决方案6】:

    我创建了一个小型工作示例,只需几个步骤即可将源文件夹复制到另一个目标文件夹(基于 shift66's answer 使用 ncp):

    第 1 步 - 安装 ncp 模块:

    npm install ncp --save
    

    第 2 步 - 创建 copy.js(根据需要修改 srcPathdestPath 变量):

    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.');
    });
    

    第 3 步 - 运行

    node copy.js
    

    【讨论】:

      【解决方案7】:

      对于 Linux/Unix 操作系统,您可以使用 shell 语法

      const shell = require('child_process').execSync;
      
      const src = `/path/src`;
      const dist = `/path/dist`;
      
      shell(`mkdir -p ${dist}`);
      shell(`cp -r ${src}/* ${dist}`);
      

      就是这样!

      【讨论】:

      • 不客气?
      • 这是最简单的解决方案。无需重新发明 UNIX 工具!
      • 因为 nodejs 在 OSX/linux/windows 上运行,这只是 2 而不是全部 3 的答案。
      • @AbdennourTOUMI 如果你在 Windows 服务器上运行会怎样。
      • 这就是为什么我以“对于 linux/unix 操作系统,您可以使用 shell 语法..”开始回答的原因 ??
      【解决方案8】:

      fs-extra 模块就像一个魅力。

      安装 fs-extra:

      $ npm install fs-extra
      

      以下是将源目录复制到目标目录的程序。

      // 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!')
      });
      

      参考文献

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

      示例:Node.js Tutorial - Node.js Copy a Folder

      【讨论】:

      • 这个过程是替换目录还是合并目录?
      【解决方案9】:

      是的,ncpcool 虽然...

      您可能希望/应该承诺其功能以使其成为super cool。当您使用它时,将其添加到 tools 文件以重复使用它。

      下面是一个工作版本,它是Async,使用Promises


      文件 index.js

      const {copyFolder} = require('./tools/');
      
      return copyFolder(
          yourSourcePath,
          yourDestinationPath
      )
      .then(() => {
          console.log('-> Backup completed.')
      }) .catch((err) => {
          console.log("-> [ERR] Could not copy the folder: ", err);
      })
      

      文件 tools.js

      const ncp = require("ncp");
      
      /**
       * Promise Version of ncp.ncp()
       *
       * This function promisifies ncp.ncp().
       * We take the asynchronous function ncp.ncp() with
       * callback semantics and derive from it a new function with
       * promise semantics.
       */
      ncp.ncpAsync = function (sourcePath, destinationPath) {
        return new Promise(function (resolve, reject) {
            try {
                ncp.ncp(sourcePath, destinationPath, function(err){
                    if (err) reject(err); else resolve();
                });
            } catch (err) {
                reject(err);
            }
        });
      };
      
      /**
       * Utility function to copy folders asynchronously using
       * the Promise returned by ncp.ncp().
       */
      const copyFolder = (sourcePath, destinationPath) => {
          return ncp.ncpAsync(sourcePath, destinationPath, function (err) {
              if (err) {
                  return console.error(err);
              }
          });
      }
      module.exports.copyFolder = copyFolder;
      

      【讨论】:

        【解决方案10】:

        Mallikarjun M, thank you!

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

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

        【讨论】:

          【解决方案11】:

          解决这个问题最简单的方法是只使用'fs'和'Path'模块和一些逻辑......

          如果您只想设置版本号,则使用 新名称 复制根文件夹中的所有文件,即 " var v = 'Your Directory Name'"

          在文件名前缀加上文件名的内容。

          var fs = require('fs-extra');
          var path = require('path');
          
          var c = 0;
          var i = 0;
          var v = "1.0.2";
          var copyCounter = 0;
          var directoryCounter = 0;
          var directoryMakerCounter = 0;
          var recursionCounter = -1;
          var Flag = false;
          var directoryPath = [];
          var directoryName = [];
          var directoryFileName = [];
          var fileName;
          var directoryNameStorer;
          var dc = 0;
          var route;
          
          if (!fs.existsSync(v)) {
              fs.mkdirSync(v);
          }
          
          var basePath = path.join(__dirname, v);
          
          
          function walk(dir) {
          
              fs.readdir(dir, function(err, items) {
          
                  items.forEach(function(file) {
          
                      file = path.resolve(dir, file);
          
                      fs.stat(file, function(err, stat) {
          
                          if(stat && stat.isDirectory()) {
                              directoryNameStorer = path.basename(file);
                              route = file;
                              route = route.replace("gd", v);
          
                              directoryFileName[directoryCounter] = route;
                              directoryPath[directoryCounter] = file;
                              directoryName[directoryCounter] = directoryNameStorer;
          
                              directoryCounter++;
                              dc++;
          
                              if (!fs.existsSync(basePath + "/" + directoryName[directoryMakerCounter])) {
                                  fs.mkdirSync(directoryFileName[directoryMakerCounter]);
                                  directoryMakerCounter++;
                              }
                          }
                          else {
                              fileName = path.basename(file);
                              if(recursionCounter >= 0) {
                                  fs.copyFileSync(file, directoryFileName[recursionCounter] + "/" + v + "_" + fileName, err => {
                                      if(err) return console.error(err);
                                  });
                                  copyCounter++;
                              }
                              else {
                                  fs.copyFileSync(file, v + "/" + v + "_" + fileName, err => {
                                      if(err) return console.error(err);
                                  });
                                  copyCounter++;
                              }
                          }
                          if(copyCounter + dc == items.length && directoryCounter > 0 && recursionCounter < directoryMakerCounter-1) {
                              console.log("COPY COUNTER:             " + copyCounter);
                              console.log("DC COUNTER:               " + dc);
                              recursionCounter++;
                              dc = 0;
                              copyCounter = 0;
                              console.log("ITEM DOT LENGTH:          " + items.length);
                              console.log("RECURSION COUNTER:        " + recursionCounter);
                              console.log("DIRECOTRY MAKER COUNTER:  " + directoryMakerCounter);
                              console.log(": START RECURSION:        " + directoryPath[recursionCounter]);
                              walk(directoryPath[recursionCounter]); //recursive call to copy sub-folder
                          }
                      })
                  })
              });
          }
          
          walk('./gd', function(err, data) { // Just pass the root directory which you want to copy
              if(err)
                  throw err;
              console.log("done");
          })
          

          【讨论】:

            【解决方案12】:

            这就是我个人的做法:

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

            它适用于文件夹和文件。

            【讨论】:

            • 这个解决方案简洁明了。这几乎就是我的做法,所以我要 +1。您应该在代码中使用 cmets 改进您的答案,并描述为什么该解决方案优于其他解决方案以及它可能有哪些缺点。 -- 还要更新它需要的模块。 ("路径", "fs")
            • 检查文件夹是否存在于顶部...将挽救生命 ;-) if (!fs.existsSync(to)) fs.mkdirSync(to);
            • 这是一个很棒的 sn-p,不需要外部依赖。 Node.js 应该能够在没有外部附加组件的情况下自行复制目录,就像这段代码所示。我想知道,将其扩展为异步工作是否容易?
            【解决方案13】:

            这对于 Node.js 10 来说非常简单:

            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 不存在。

            【讨论】:

            • 我们可以通过使用 require('util').promisifyfs.mkdirfs.copyFile 而不是 require('fs').promises 来使其在 Node 8.x 中工作,而 require('fs').promises 在 v11.1 中仍处于试验阶段。
            • @sntran 8.x 是否有withFileTypes 选项?因为这样可以为您节省一个stat 电话
            • 很遗憾,8.x 没有withFileTypes 选项。
            • @SơnTrần-Nguyễn 8.x 将于 2019 年 12 月 31 日结束生命周期 - 可能是时候升级了 :-)
            【解决方案14】:

            我就是这样做的:

            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)
            

            【讨论】:

              【解决方案15】:

              我尝试使用 fs-extra 和 copy-dir 递归地复制文件夹。但我想要它

              1. 正常工作(copy-dir抛出不合理的错误)
              2. 在过滤器中提供两个参数:文件路径和文件类型(fs-extra 不告诉文件类型)
              3. 进行目录到子目录检查和目录到文件检查

              所以我自己写了:

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

              【讨论】:

                【解决方案16】:

                我为在目录之间递归地复制 (copyFileSync) 或移动 (renameSync) 文件编写了这个函数:

                // 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, targetPath);
                        }
                        else {
                            operation(sourcePath, targetPath);
                        }
                    });
                }
                

                【讨论】:

                  【解决方案17】:

                  我知道这里已经有很多答案了,但没有人以简单的方式回答。

                  关于 fs-exra official documentation,你可以很容易地做到。

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

                  【讨论】:

                  • 确保设置递归选项。 fs.copySync('/tmp/mydir', '/tmp/mynewdir',{ recursive: true })
                  • 我找不到你提到的github doc中的option{ recursive: true },不知道是否有效。
                  • 我猜我们在谈论 fs-extra,但您的 github 链接指向 node-fs-extra。可能是不同的图书馆吗?
                  • @DheerajKumar,它在 github 中显示 node-fs-extra,但在 npm 中显示 fs-extra。我不知道两者是否相同,请参考npm的包裹
                  • fs-extra 会替代 fs 吗?
                  【解决方案18】:

                  如果您使用的是 Linux,并且性能不是问题,您可以使用 child_process 模块中的 exec 函数来执行 Bash 命令:

                  const { exec } = require('child_process');
                  exec('cp -r source dest', (error, stdout, stderr) => {...});
                  

                  在某些情况下,我发现此解决方案比下载整个模块甚至使用 fs 模块更简洁。

                  【讨论】:

                  • 正如许多 cmet 在之前的解决方案中已经指出的那样:这不是跨平台的!
                  • OP 没有要求跨平台解决方案,我已经指出这仅适用于 Linux。
                  【解决方案19】:

                  挑选包裹时要小心。某些包(如 copy-dir)不支持复制长度超过 0X1FFFFFE8 个字符(约 537 MB)的大文件。

                  它会抛出一些错误,例如:

                  buffer.js:630 未捕获错误:无法创建长度超过 0x1fffffe8 个字符的字符串

                  我在我的一个项目中经历过类似的事情。最终,我不得不更改我正在使用的包并调整大量代码。我会说这不是一次非常愉快的经历。

                  如果需要多个源和多个目标副本,您可以使用better-copy 并编写如下内容:

                  // Copy from multiple source into a directory
                  bCopy(['/path/to/your/folder1', '/path/to/some/file.txt'], '/path/to/destination/folder');
                  

                  甚至:

                  // Copy from multiple source into multiple destination
                  bCopy(['/path/to/your/folder1', '/path/to/some/file.txt'], ['/path/to/destination/folder', '/path/to/another/folder']);
                  

                  【讨论】:

                    【解决方案20】:

                    具有符号链接支持的那个:

                    const path = require("path");
                    const {
                      existsSync,
                      mkdirSync,
                      readdirSync,
                      lstatSync,
                      copyFileSync,
                      symlinkSync,
                      readlinkSync,
                    } = require("fs");
                    
                    export function copyFolderSync(src, dest) {
                      if (!existsSync(dest)) {
                        mkdirSync(dest);
                      }
                    
                      readdirSync(src).forEach((entry) => {
                        const srcPath = path.join(src, entry);
                        const destPath = path.join(dest, entry);
                        const stat = lstatSync(srcPath);
                    
                        if (stat.isFile()) {
                          copyFileSync(srcPath, destPath);
                        } else if (stat.isDirectory()) {
                          copyFolderSync(srcPath, destPath);
                        } else if (stat.isSymbolicLink()) {
                          symlinkSync(readlinkSync(srcPath), destPath);
                        }
                      });
                    }
                    

                    【讨论】:

                      【解决方案21】:

                      看起来ncpwrench 两者都不再维护。可能最好的选择是使用fs-extra

                      Wrench 的开发者指示用户使用 fs-extra,因为他已经弃用了他的库

                      copySyncmoveSync 都会复制和移动文件夹,即使它们有文件或子文件夹,您也可以使用它轻松移动或复制文件

                      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);      |___{ overwrite: true } // add if you want to replace existing folder or file with same name
                        } else {
                          console.log("success!");
                        }
                      });
                      

                      // To Move a folder or file  
                      fse.moveSync(srcDir, destDir, function (err) {
                        if (err) {                 ^
                          console.error(err);      |___{ overwrite: true } // add if you want to replace existing folder or file with same name
                        } else {
                          console.log("success!");
                        }
                      });
                      

                      【讨论】:

                      • fse copySync 不接受回调:github.com/jprichardson/node-fs-extra/blob/HEAD/docs/…。如果你想检测错误,你应该尝试捕捉:try { fse.copySync('/tmp/myfile', '/tmp/mynewfile'); console.log('success!');} catch (err) { console.error(err);}
                      • copySync 的参数已更改,第三个参数是选项对象,而不是回调:github.com/jprichardson/node-fs-extra/blob/master/docs/…
                      • FYI 节点有实验性的fs.cpnodejs.org/api/fs.html#fs_fspromises_cp_src_dest_options,它>“将整个目录结构从 src 异步复制到 dest,包括子目录和文件。”
                      • 嗨@GeorgiyBukharov 这将有所帮助,但截至目前,它在 Node v16.7.0 中仍处于实验阶段。在 node 的未来版本中将很容易使用。
                      • 只是为了澄清,copySync 根据它的实现它接受 opts 对象或函数。然而,作为第三个参数的函数被视为过滤选项,而不是回调。
                      【解决方案22】:

                      如果要递归复制源目录的所有内容,则需要将recursive 选项传递为truetry catch 由fs-extra 记录为sync

                      由于fs-extra 完全替代了fs,所以您不需要导入基本模块

                      const fs = require('fs-extra');
                      let sourceDir = '/tmp/src_dir';
                      let destDir = '/tmp/dest_dir';
                      try {
                        fs.copySync(sourceDir, destDir, { recursive: true })
                        console.log('success!')
                      } catch (err) {
                        console.error(err)
                      }
                      
                      

                      【讨论】:

                        【解决方案23】:

                        使用shelljs

                        npm i -D shelljs

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

                        【讨论】:

                          【解决方案24】:

                          另一种使用 glob 通配符复制文件的方法。 使用它,您可以有选择地复制,例如/my/dir/**/*.js

                          const glob = require('glob');
                          const path = require('path');
                          const fs = require('fs');
                          
                          function copy(from, to) { //accepting glob pattern
                            const wildcard = from.indexOf('*') !== -1;
                            const pattern = !wildcard && fs.lstatSync(from).isDirectory() ? `${from}/**/*` : from;
                            glob.sync(pattern).forEach(file => {
                              const fromDirname = path.dirname(from.replace(/\/\*.*/, '/wildcard'));
                              const target = file.replace(fromDirname, to);
                              const [targetDir, recursive] = [path.dirname(target), true];
                              !fs.existsSync(targetDir) && fs.mkdirSync(targetDir, {recursive});
                              fs.lstatSync(file).isDirectory() ? 
                                fs.mkdirSync(target, {recursive}) : fs.copyFileSync(file, target);
                            })
                          }
                          

                          例子

                          copy('src/tools', 'dist')
                          copy('src/components/**/*', 'dist/elements')
                          copy('src/*.html', 'dist')
                          copy('src/*.css', 'dist')
                          copy('public/*', 'dist')
                          

                          【讨论】:

                            【解决方案25】:

                            从 Node v16.7.0 开始,可以使用 fs.cpfs.cpSync 函数。

                            fs.cp(src, dest, {recursive: true});
                            

                            当前稳定性(在 Node v17.0.1 中)为 Experimental

                            【讨论】:

                              猜你喜欢
                              • 2015-12-03
                              • 2019-11-04
                              • 2011-01-12
                              • 2016-06-06
                              • 2018-02-07
                              • 2014-10-20
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多