Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move all files in directory to parent with node.js

Tags:

node.js

fs

mv

Question

Is there a simple way to move all the files in a directory up to its parent directory then delete the directory?

Use Case

I'm doing a zip extraction and the source zip contains a root folder called archive, so when I extract I get extract_path/archive/, but I'd like to just extract the contents of archive directly to extract_path.

I thought this would be simple rename, but the following is throwing a "There is a file in the way" error message.

fs.renameSync(extractPath + "/archive", extractPath)
like image 402
Ralph Callaway Avatar asked Oct 10 '14 03:10

Ralph Callaway


People also ask

How to move files from one directory to another directory in NodeJS?

In this tutorial, we are going to learn about how to move the files from one directory to another directory in Node.js. Node.js has a built-in file system module, which has an fs.rename () method that helps us to asynchronously move a file from one directory to another.

How do I get a list of all files in node?

Let's get the files now. The most familiar way to Node.js get all files in directory is to use the fs (file system) module with methods like readdir () and readdirSync (). You can asynchronously list files in a directory using the readdir () method.

How do I create a new folder in Node JS?

The Node.js fs core module provides many handy methods you can use to work with folders. Use fs.access () (and its promise-based fsPromises.access () counterpart) to check if the folder exists and Node.js can access it with its permissions. Use fs.mkdir () or fs.mkdirSync () or fsPromises.mkdir () to create a new folder.

How to asynchronously move a file from one directory to another?

Node.js has a built-in file system module, which has an fs.rename () method that helps us to asynchronously move a file from one directory to another. Here is an example:


2 Answers

Non of the answers work for me, I looked deep in mv's code and found my solution:

I move folder/subfolder to folder, so the folder already exists.

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

Remember if the filename already exists in parent folder it will overwrite by file inside subfolder.

like image 94
Cava Avatar answered Sep 16 '22 11:09

Cava


The selected answer does not work:

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

It errors with:

{ 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' }

Use fs-extra instead of mv:

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

My file structure is like this before the move:

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

And like this after the move:

E:\tmp\dir
    > doc.txt

UPDATE:

While the above works on Windows, on Linux I get the same error even when using fs-extra. The below is a manual fix for this, by individually moving each child of the subdirectory up to the parent. If a child move fails, then it will revert any other successful moves back to the original location in the subdirectory.

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);
        });
    });
};
like image 42
user2426679 Avatar answered Sep 19 '22 11:09

user2426679