【问题标题】:Move all files in directory to parent with node.js使用 node.js 将目录中的所有文件移动到父级
【发布时间】:2014-12-05 03:56:48
【问题描述】:

问题

有没有一种简单的方法可以将目录中的所有文件移动到其父目录然后删除该目录?

用例

我正在进行 zip 提取,源 zip 包含一个名为 archive 的根文件夹,所以当我提取时我得到 extract_path/archive/,但我想直接将 archive 的内容提取到 @ 987654324@.

我认为这将是简单的重命名,但以下是抛出“有一个文件在路上”错误消息。

fs.renameSync(extractPath + "/archive", extractPath)

【问题讨论】:

    标签: node.js mv fs


    【解决方案1】:

    没有一个答案对我有用,我深入研究了 mv 的代码并找到了我的解决方案:

    我将folder/subfolder 移动到folder,所以该文件夹已经存在。

    mv(oldPath, newPath, {mkdirp: false, clobber: false}, (err) => {
        if (err) {
            throw err;
        }
    });
    

    请记住,如果父文件夹中已经存在该文件名,它将被子文件夹中的文件覆盖。

    【讨论】:

      【解决方案2】:

      所选答案无效:

      var mv = require('mv');
      var extractPath = 'E:\\tmp\\dir';
      mv(extractPath + "\\sub", extractPath, {mkdirp: true}, console.error);
      

      错误:

      { Error: EPERM: operation not permitted, rename 'E:\tmp\dir\sub' -> 'E:\tmp\dir'
          at Error (native)
        errno: -4048,
        code: 'EPERM',
        syscall: 'rename',
        path: 'E:\\tmp\\dir\\sub',
        dest: 'E:\\tmp\\dir' }
      

      使用 fs-extra 代替 mv:

      var fs = require('fs-extra');
      var extractPath = 'E:\\tmp\\dir';
      fs.move(extractPath + "\\sub", extractPath, console.error);
      

      搬家前我的文件结构是这样的:

      E:\tmp\dir
          > sub
              > doc.txt
      

      搬家后是这样的:

      E:\tmp\dir
          > doc.txt
      

      更新:

      虽然上述方法适用于 Windows,但在 Linux 上,即使使用 fs-extra,我也会遇到同样的错误。下面是对此的手动修复,通过将子目录的每个子目录单独移动到父目录。如果子移动失败,那么它会将任何其他成功的移动恢复到子目录中的原始位置。

      var fs = require('fs-extra')
      var Promise = require('promise');
      var path = require('path');
      
      
      var promiseAllWait = function(promises) {
          // this is the same as Promise.all(), except that it will wait for all promises to fulfill before rejecting
          var all_promises = [];
          for(var i_promise=0; i_promise < promises.length; i_promise++) {
              all_promises.push(
                  promises[i_promise]
                  .then(function(res) {
                      return { res: res };
                  }).catch(function(err) {
                      return { err: err };
                  })
              );
          }
      
          return Promise.all(all_promises)
          .then(function(results) {
              return new Promise(function(resolve, reject) {
                  var is_failure = false;
                  var i_result;
                  for(i_result=0; i_result < results.length; i_result++) {
                      if (results[i_result].err) {
                          is_failure = true;
                          break;
                      } else {
                          results[i_result] = results[i_result].res;
                      }
                  }
      
                  if (is_failure) {
                      reject( results[i_result].err );
                  } else {
                      resolve(results);
                  }
              });
          });
      };
      
      var movePromiser = function(from, to, records) {
          return fs.move(from, to)
          .then(function() {
              records.push( {from: from, to: to} );
          });
      };
      
      var moveDir = function(from_dir, to_dir) {
          return fs.readdir(from_dir)
          .then(function(children) {
              return fs.ensureDir(to_dir)
              .then(function() {
                  var move_promises = [];
                  var moved_records = [];
                  var child;
                  for(var i_child=0; i_child < children.length; i_child++) {
                      child = children[i_child];
                      move_promises.push(movePromiser(
                          path.join(from_dir, child),
                          path.join(to_dir, child),
                          moved_records
                      ));
                  }
      
                  return promiseAllWait(move_promises)
                  .catch(function(err) {
                      var undo_move_promises = [];
                      for(var i_moved_record=0; i_moved_record < moved_records.length; i_moved_record++) {
                          undo_move_promises.push( fs.move(moved_records[i_moved_record].to, moved_records[i_moved_record].from) );
                      }
      
                      return promiseAllWait(undo_move_promises)
                      .then(function() {
                          throw err;
                      });
                  });
              }).then(function() {
                  return fs.rmdir(from_dir);
              });
          });
      };
      

      【讨论】:

        【解决方案3】:

        使用mv npm 模块。 mv 首先尝试 fs.rename,如果失败,则使用复制然后取消链接:

        mv('source/dir', 'dest/a/b/c/dir', {mkdirp: true}, function(err) {
          // done. it first created all the necessary directories, and then
          // tried fs.rename, then falls back to using ncp to copy the dir
          // to dest and then rimraf to remove the source dir
        });
        

        或产生一个子进程:

        var spawn = require('child_process').spawn,
            mv = spawn('mv', ['/dir1/dir2/*','dir1/']);
        

        【讨论】:

        • 如果有同步版本,你会吗?
        • 使用 execSync:var spawn = require('child_precess').execSync;
        • 此答案不适用于将子目录的内容移动到父目录(问题提出)。运行 mv('E:\\tmp\\dir\\sub', 'E:\\tmp\\dir', {mkdirp: true}, console.error); 失败并显示 Error: EPERM: operation not permitted, rename 'E:\tmp\dir\sub' -&gt; 'E:\tmp\dir'
        • 当 dst 目录不为空时不工作。 [错误:ENOTEMPTY:目录不为空,]
        猜你喜欢
        • 1970-01-01
        • 2017-05-27
        • 2016-04-10
        • 1970-01-01
        • 2016-05-03
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多