Node.js 复制文件/文件夹的实现

 2016年03月24日    6038     声明


在Node.js中,操作文件和目录使用fs模块,但在这个模块并没有直接提供文件或目录复制的方法。要实现文件和目录的复制,我们可以借助fs中的一些方法实现。


  1. 文件的复制
  2. 文件夹的复制
  3. 使用Linux命令复制

1. 文件的复制

文件的复制我们可以通过fs.readFile()方法读取文件,再通过fs.writeFile()方法写入到一个新文件实现:

var fs = require('fs');

function copyFile(src, dist) {
  fs.writeFileSync(dist, fs.readFileSync(src));
}

如,将当前文件夹下的a.txt复制为aa.txt

copyFile('./a.txt', './aa.txt')


大文件的复制

fs.readFile()方法(fs.readFileSync()为其同步版本的方法)会整体将文件读取到内存中。当文件较大时,会对系统资源造成一定压力,这时我们可能以通过文件来进行操作。fs模块同样提供了基于文件流的操作方法,fs.createReadStream()和fs.createWriteStream(),可以copyFile()方法修改如下:

function copyFile(src, dist) {
  fs.createReadStream(src).pipe(fs.createWriteStream(dist));
}


2. 文件夹的复制

文件夹(目录)的复制不同于文件的复制,文件夹操作时还要考虑操作对象是否存在及操作对象的类型(文件或目录)。在早期的Node.js版本中,可以使用fs.exists()判断文件或文件夹是否存在,但在v4.0+之后,这个方法已经被废弃,判断文件或目录是否存在需要使用fs.stat()fs.access()方法。下面是一个复制目录的方法:

var fs = require( 'fs' );

/*
 * 复制目录、子目录,及其中的文件
 * @param src {String} 要复制的目录
 * @param dist {String} 复制到目标目录
 */
function copyDir(src, dist, callback) {
  fs.access(dist, function(err){
    if(err){
      // 目录不存在时创建目录
      fs.mkdirSync(dist);
    }
    _copy(null, src, dist);
  });

  function _copy(err, src, dist) {
    if(err){
      callback(err);
    } else {
      fs.readdir(src, function(err, paths) {
        if(err){
          callback(err)
        } else {
          paths.forEach(function(path) {
            var _src = src + '/' +path;
            var _dist = dist + '/' +path;
            fs.stat(_src, function(err, stat) {
              if(err){
                callback(err);
              } else {
                // 判断是文件还是目录
                if(stat.isFile()) {
                  fs.writeFileSync(_dist, fs.readFileSync(_src));
                } else if(stat.isDirectory()) {
                  // 当是目录是,递归复制
                  copyDir(_src, _dist, callback)
                }
              }
            })
          })
        }
      })
    }
  }
}

如,复制./test目录到./new目录:

copyDir('./test', './new', function(err){
  if(err){
    console.log(err);
  }
})

注意:上面这个对目录处理的方式比较简单,在实际操作目录时,如果上级目录不存在会出现错误,这时应该结合path模块逐级判断目录是否存在。


3. 使用Linux命令复制

使用Linux命令复制目录非常简单,复制一个目录可以使用cp -r 源目录 目标目录实现。Node.js的child_process使我们可以执行外部命令。

下面是使用child_process模块实现文件复制的示例:

var child_process = require('child_process');

function copyDir(src, dist) {
  child_process.spawn('cp', ['-r', src, dist]);	
}

如,使用这个方法复制./test目录到./new目录:

copyDir('./test', './new');

注意:使用child_process复制目录时,同样需要判断目标目录,应该结合path模块逐级判断目录是否存在。