Copy folder recursively in Node.js

前端 未结 25 1808
隐瞒了意图╮
隐瞒了意图╮ 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:21

    Yes, ncp is cool though...

    You might want/should promisify its function to make it super cool. While you're at it, add it to a tools file to reuse it.

    Below is a working version which is Async and uses Promises.


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

    File 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;
    
    0 讨论(0)
  • 2020-12-04 08:23

    This is my approach to solve this problem without any extra modules. Just using the built-in fs and path modules.

    Note: This does use the read / write functions of fs, so it does not copy any meta data (time of creation, etc.). As of Node.js 8.5 there is a copyFileSync function available which calls the OS copy functions and therefore also copies meta data. I did not test them yet, but it should work to just replace them. (See 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 );
                }
            } );
        }
    }
    
    0 讨论(0)
  • 2020-12-04 08:26

    This is pretty easy with 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);
            }
        }
    }
    

    This assumes dest does not exist.

    0 讨论(0)
  • 2020-12-04 08:26

    This code will work just fine, recursively copying any folder to any location. But it is Windows only.

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

    It works perfectly for my textbased game for creating new players.

    0 讨论(0)
  • 2020-12-04 08:28

    I created a small working example that copies a source folder to another destination folder in just a few steps (based on shift66's answer using ncp):

    Step 1 - Install ncp module:

    npm install ncp --save
    

    Step 2 - create copy.js (modify the srcPath and destPath variables to whatever you need):

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

    Step 3 - run

    node copy.js
    
    0 讨论(0)
  • 2020-12-04 08:29

    Here's a function that recursively copies a directory and its contents to another directory:

    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);
      }
    };
    
    0 讨论(0)
提交回复
热议问题