使用 node.js 将目录中的所有文件移动到父级

Posted

技术标签:

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

问题

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

用例

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

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

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

【问题讨论】:

【参考方案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:目录不为空,]

以上是关于使用 node.js 将目录中的所有文件移动到父级的主要内容,如果未能解决你的问题,请参考以下文章

将班级名称从子级移动到父级

如何通过 * 将包括隐藏文件在内的所有文件移动到父目录中

如何在树结构中从子级移动到父级?

PyQt5:QPushButton 上的 setParent 不会将其添加到父级

将嵌套数据框扩展到父级

JQuery Draggable - 限制到父级,但允许在父级下滑动?