229

How can I move files (like mv command shell) on node.js? Is there any method for that or should I read a file, write to a new file and remove older file?

Chris Kobrzak
  • 1,044
  • 14
  • 20
rizidoro
  • 13,073
  • 18
  • 59
  • 86

17 Answers17

230

According to seppo0010 comment, I used the rename function to do that.

http://nodejs.org/docs/latest/api/fs.html#fs_fs_rename_oldpath_newpath_callback

fs.rename(oldPath, newPath, callback)

Added in: v0.0.2

oldPath <String> | <Buffer>
newPath <String> | <Buffer>
callback <Function>

Asynchronous rename(2). No arguments other than a possible exception are given to the completion callback.

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
rizidoro
  • 13,073
  • 18
  • 59
  • 86
  • 6
    For those wondering where @seppo0010's comment went: it was on my answer, which I deleted and posted as a comment on the OP. – Matt Ball Dec 20 '11 at 18:46
  • 10
    This will not work if you are crossing partitions or using a virtual filesystem not supporting moving files. You better use [this solution](http://stackoverflow.com/a/29105404/532695) with a copy fallback – Flavien Volken Sep 02 '15 at 12:50
109

Using nodejs natively

var fs = require('fs')

var oldPath = 'old/path/file.txt'
var newPath = 'new/path/file.txt'

fs.rename(oldPath, newPath, function (err) {
  if (err) throw err
  console.log('Successfully renamed - AKA moved!')
})

(NOTE: "This will not work if you are crossing partitions or using a virtual filesystem not supporting moving files. [...]" – Flavien Volken Sep 2 '15 at 12:50")

marcel
  • 2,967
  • 1
  • 16
  • 25
Hani
  • 2,122
  • 1
  • 17
  • 17
  • crossing partitions? what? you mean moving between filesystems? – france1 Jan 24 '23 at 14:47
  • It's an advanced way of connecting multiple servers, or using virtualization platforms like Docker, and what not, if you don't know it then you shouldn't be worry about it, the other user added that note to my answer, although I don't see the need for it in this context. – Hani Jan 24 '23 at 17:47
  • I think he rather meant moving between files systems, not just docker or network. It's important to add that. Just saying "partitions" is a bit confisuing, though. – france1 Jan 24 '23 at 19:34
60

This example taken from: Node.js in Action

A move() function that renames, if possible, or falls back to copying

var fs = require('fs');

module.exports = function move(oldPath, newPath, callback) {

    fs.rename(oldPath, newPath, function (err) {
        if (err) {
            if (err.code === 'EXDEV') {
                copy();
            } else {
                callback(err);
            }
            return;
        }
        callback();
    });

    function copy() {
        var readStream = fs.createReadStream(oldPath);
        var writeStream = fs.createWriteStream(newPath);

        readStream.on('error', callback);
        writeStream.on('error', callback);

        readStream.on('close', function () {
            fs.unlink(oldPath, callback);
        });

        readStream.pipe(writeStream);
    }
}
sam
  • 931
  • 2
  • 13
  • 26
Teoman shipahi
  • 47,454
  • 15
  • 134
  • 158
  • 4
    Worked like a charm. Thanks! If I may add a little bit: 'move' might be a better name when it unlinks oldPath. – Jokester Feb 18 '17 at 16:41
  • The copy() function is OK in this case, but if someone means to wrap it inside a Promise object, please either see my "answer" below or keep in mind to resolve the promise upon the "close" event on the write stream, not on the read stream. – Jem Dec 12 '18 at 10:31
  • This looks like something that'll work for my needs, however I don't know how to use the module.exports = function { } style. do I copy this code into my app itself where I already have var fs = require('fs'); and then call fs.move(oldFile, newFile, function(err){ .... }) instead of fs.rename ? – Curious101 Apr 12 '19 at 04:56
  • @Curious101 You can put this in a file like filemove.js and import it like var filemove = require('filemove'); then use it like filemove(...); – Teoman shipahi Apr 13 '19 at 02:21
  • Thanks @Teomanshipahi. In that case I can add to mylibrary.js and use it from there. I thought this was some well known method of adding prototype methods so it becomes available in the object itself. – Curious101 Apr 13 '19 at 23:22
  • Shouldn't the call unlink have a condition that there were no errors? (the v16 docs are clear that a 'close' can happen after an 'error'.) In that scenario, you'd callback(err), then delete the file you didn't successfully copy, then callback() again. (The fact that promises can't be triggered more than once is convenient here, but the promisified code in the other answer has the same "deletes unmoved file" pattern... assuming I'm reading the event docs right.) – xander Jul 04 '21 at 04:45
31

Use the mv node module which will first try to do an fs.rename and then fallback to copying and then unlinking.

andrewrk
  • 30,272
  • 27
  • 92
  • 113
  • Worked well for the simple requirements to move a file. – arcseldon Aug 10 '15 at 23:29
  • 2
    andrewrk appears to be the author of this `mv` node module. I like using npm to install ; `npm install mv --save-dev`; here's the [npm link](https://www.npmjs.com/package/mv) – Nate Anderson Jun 23 '17 at 03:27
  • 9
    How's this a dev dependency? Doesn't the app require mv in order to function? – jgr0 Feb 18 '19 at 08:08
19

util.pump is deprecated in node 0.10 and generates warning message

 util.pump() is deprecated. Use readableStream.pipe() instead

So the solution for copying files using streams is:

var source = fs.createReadStream('/path/to/source');
var dest = fs.createWriteStream('/path/to/dest');

source.pipe(dest);
source.on('end', function() { /* copied */ });
source.on('error', function(err) { /* error */ });
deadrunk
  • 13,861
  • 4
  • 29
  • 29
19

The fs-extra module allows you to do this with its move() method. I already implemented it and it works well if you want to completely move a file from one directory to another - ie. removing the file from the source directory. Should work for most basic cases.

var fs = require('fs-extra')

fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile', function (err) {
 if (err) return console.error(err)
 console.log("success!")
})
mikeym
  • 5,705
  • 8
  • 42
  • 62
  • I believe fs-extra returns promises as well so you can use async/await – Anthony Sep 20 '20 at 21:32
  • 1
    fs-extra is a good choice because it **correctly** handles the case where it needs to move the file across devices (cases where _rename_ fails, as cautioned in may other answers here, such as Docker volumes.) [Code evidence here](https://github.com/jprichardson/node-fs-extra/blob/e6a95058c930953113177c9518f57e83cace3e79/lib/move/move.js#L58) – Wyck Aug 23 '21 at 17:46
16

Using promises for Node versions greater than 8.0.0:

const {promisify} = require('util');
const fs = require('fs');
const {join} = require('path');
const mv = promisify(fs.rename);

const moveThem = async () => {
  // Move file ./bar/foo.js to ./baz/qux.js
  const original = join(__dirname, 'bar/foo.js');
  const target = join(__dirname, 'baz/qux.js'); 
  await mv(original, target);
}

moveThem();
TheBosti
  • 1,354
  • 13
  • 19
vorillaz
  • 6,098
  • 2
  • 30
  • 46
9

Using the rename function:

fs.rename(getFileName, __dirname + '/new_folder/' + getFileName); 

where

getFilename = file.extension (old path)
__dirname + '/new_folder/' + getFileName

assumming that you want to keep the file name unchanged.

alex
  • 479,566
  • 201
  • 878
  • 984
julia
  • 452
  • 6
  • 15
  • 5
    Be careful this will not work if you try to rename the file between different partitions, neither on some virtual file systems (such as docker for instance) – Flavien Volken Sep 02 '15 at 12:47
5

Here's an example using util.pump, from >> How do I move file a to a different partition or device in Node.js?

var fs = require('fs'),
    util = require('util');

var is = fs.createReadStream('source_file')
var os = fs.createWriteStream('destination_file');

util.pump(is, os, function() {
    fs.unlinkSync('source_file');
});
Community
  • 1
  • 1
alessioalex
  • 62,577
  • 16
  • 155
  • 122
  • 21
    It's worth noting that you only have to do this when moving files across volumes. Otherwise, you can just use [`fs.rename()`](http://nodejs.org/docs/latest/api/fs.html#fs.rename) (within a volume renaming a file and moving it are the same thing). – s4y Dec 20 '11 at 18:42
  • http://stackoverflow.com/questions/4568689/how-do-i-move-file-a-to-a-different-partition-in-node-js#comment17237127_4571377 –  May 03 '13 at 16:55
  • Is possible to move file from local machine to server? – Hulk1991 Jul 31 '13 at 05:31
  • Nope, you need to use something else for that (like using FTP, HTTP or another protocol). – alessioalex Jul 31 '13 at 08:31
4

Just my 2 cents as stated in the answer above : The copy() method shouldn't be used as-is for copying files without a slight adjustment:

function copy(callback) {
    var readStream = fs.createReadStream(oldPath);
    var writeStream = fs.createWriteStream(newPath);

    readStream.on('error', callback);
    writeStream.on('error', callback);

    // Do not callback() upon "close" event on the readStream
    // readStream.on('close', function () {
    // Do instead upon "close" on the writeStream
    writeStream.on('close', function () {
        callback();
    });

    readStream.pipe(writeStream);
}

The copy function wrapped in a Promise:

function copy(oldPath, newPath) {
  return new Promise((resolve, reject) => {
    const readStream = fs.createReadStream(oldPath);
    const writeStream = fs.createWriteStream(newPath);

    readStream.on('error', err => reject(err));
    writeStream.on('error', err => reject(err));

    writeStream.on('close', function() {
      resolve();
    });

    readStream.pipe(writeStream);
  })

However, keep in mind that the filesystem might crash if the target folder doesn't exist.

Jem
  • 6,226
  • 14
  • 56
  • 74
4

fs.rename is also available in the sync version:

fs.renameSync(oldPath, newPath)
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Nben
  • 127
  • 7
3

I would separate all involved functions (i.e. rename, copy, unlink) from each other to gain flexibility and promisify everything, of course:

const renameFile = (path, newPath) => 
  new Promise((res, rej) => {
    fs.rename(path, newPath, (err, data) =>
      err
        ? rej(err)
        : res(data));
  });

const copyFile = (path, newPath, flags) =>
  new Promise((res, rej) => {
    const readStream = fs.createReadStream(path),
      writeStream = fs.createWriteStream(newPath, {flags});

    readStream.on("error", rej);
    writeStream.on("error", rej);
    writeStream.on("finish", res);
    readStream.pipe(writeStream);
  });

const unlinkFile = path => 
  new Promise((res, rej) => {
    fs.unlink(path, (err, data) =>
      err
        ? rej(err)
        : res(data));
  });

const moveFile = (path, newPath, flags) =>
  renameFile(path, newPath)
    .catch(e => {
      if (e.code !== "EXDEV")
        throw new e;

      else
        return copyFile(path, newPath, flags)
          .then(() => unlinkFile(path));
    });

moveFile is just a convenience function and we can apply the functions separately, when, for example, we need finer grained exception handling.

3

If you are fine with using an external library, Shelljs is a very handy solution.

command: mv([options ,] source, destination)

Available options:

-f: force (default behaviour)

-n: to prevent overwriting

const shell = require('shelljs');
const status = shell.mv('README.md', '/home/my-dir');
if(status.stderr)  console.log(status.stderr);
else console.log('File moved!');
Prayag k
  • 647
  • 9
  • 23
2

this is a rehash of teoman shipahi's answer with a slightly less ambiguous name, and following the design priciple of defining code before you attempt to call it. (Whilst node allows you to do otherwise, it's not good a practice to put the cart before the horse.)

function rename_or_copy_and_delete (oldPath, newPath, callback) {

    function copy_and_delete () {
        var readStream = fs.createReadStream(oldPath);
        var writeStream = fs.createWriteStream(newPath);

        readStream.on('error', callback);
        writeStream.on('error', callback);
        readStream.on('close', 
              function () {
                fs.unlink(oldPath, callback);
              }
        );

        readStream.pipe(writeStream);
    }

    fs.rename(oldPath, newPath, 
        function (err) {
          if (err) {
              if (err.code === 'EXDEV') {
                  copy_and_delete();
              } else {
                  callback(err);
              }
              return;// << both cases (err/copy_and_delete)
          }
          callback();
        }
    );
}
Community
  • 1
  • 1
unsynchronized
  • 4,828
  • 2
  • 31
  • 43
-1

If you are trying to move or rename a node.js source file, try this https://github.com/viruschidai/node-mv. It will update the references to that file in all other files.

-1

With the help of below URL, you can either copy or move your file CURRENT Source to Destination Source

https://coursesweb.net/nodejs/move-copy-file

/*********Moves the $file to $dir2 Start *********/
var moveFile = (file, dir2)=>{
  //include the fs, path modules
  var fs = require('fs');
  var path = require('path');

  //gets file name and adds it to dir2
  var f = path.basename(file);
  var dest = path.resolve(dir2, f);

  fs.rename(file, dest, (err)=>{
    if(err) throw err;
    else console.log('Successfully moved');
  });
};

//move file1.htm from 'test/' to 'test/dir_1/'
moveFile('./test/file1.htm', './test/dir_1/');
/*********Moves the $file to $dir2 END *********/

/*********copy the $file to $dir2 Start *********/
var copyFile = (file, dir2)=>{
  //include the fs, path modules
  var fs = require('fs');
  var path = require('path');

  //gets file name and adds it to dir2
  var f = path.basename(file);
  var source = fs.createReadStream(file);
  var dest = fs.createWriteStream(path.resolve(dir2, f));

  source.pipe(dest);
  source.on('end', function() { console.log('Succesfully copied'); });
  source.on('error', function(err) { console.log(err); });
};

//example, copy file1.htm from 'test/dir_1/' to 'test/'
copyFile('./test/dir_1/file1.htm', './test/');
/*********copy the $file to $dir2 END *********/
Abdullah
  • 2,393
  • 1
  • 16
  • 29
-5

Node.js v10.0.0+

const fs = require('fs')
const { promisify } = require('util')
const pipeline = promisify(require('stream').pipeline)

await pipeline(
  fs.createReadStream('source/file/path'),
  fs.createWriteStream('destination/file/path')
).catch(err => {
  // error handling
})
fs.unlink('source/file/path')
urin
  • 91
  • 1