如何在node.js中移动文件?


151

如何在node.js上移动文件(如mv命令外壳)?有什么方法可以使用,还是应该读取文件,写入新文件并删除旧文件?

Answers:


157

根据seppo0010的评论,我使用了重命名功能。

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

fs.rename(oldPath,newPath,回调)

在v0.0.2中添加

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

异步重命名(2)。除了可能的异常外,没有其他参数被赋予完成回调。


5
对于那些想知道@ seppo0010的评论去了哪里的人:它在我的答案上,我删除了该评论并将其发布在OP上。
马特·鲍尔

6
如果您正在跨分区或使用不支持移动文件的虚拟文件系统,则此方法将不起作用。您最好将此解决方案与副本后备结合使用
Flavien Volken 2015年

“ Hani”的第三个答案有示例代码!
内森

47

此示例摘自:运行中的Node.js

一个move()函数,如果可能的话,该函数会重命名或退回复制

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);
    }
}

3
像魅力一样工作。谢谢!如果我可以添加一点:'move'在取消oldPath链接时可能是一个更好的名称。
Jokester '17

在这种情况下,copy()函数是可以的,但是如果有人打算将其包装在Promise对象中,请要么在下面看到我的“答案”,要么紧记要解决写流中“关闭”事件的承诺,不在读取流上。
杰姆

这看起来可以满足我的需求,但是我不知道如何使用module.exports = function {}样式。我是否将此代码复制到我已经有var fs = require('fs')的应用程序本身中?然后调用fs.move(oldFile,newFile,function(err){....})而不是fs.rename吗?
Curious101 '19

@ Curious101您可以将其放入filemove.js之类的文件中,然后像var filemove = require('filemove');一样导入。然后像filemove(...)一样使用它;
Teoman shipahi

谢谢@Teomanshipahi。在那种情况下,我可以添加到mylibrary.js并从那里使用它。我认为这是添加原型方法的一些众所周知的方法,因此它可以在对象本身中使用。
Curious101 '19

35

原生使用nodejs

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!')
})

(注意:“如果您正在跨分区或使用不支持移动文件的虚拟文件系统,此操作将不起作用。[... – Flavien Volken 2015年9月2日,12:50“)


30

使用mv节点模块,该模块将首先尝试执行an fs.rename,然后回退到复制然后取消链接。


对于移动文件的简单要求,效果很好。
arcseldon

1
andrewrk似乎是该mv节点模块的作者。我喜欢使用npm进行安装;npm install mv --save-dev; 这是npm链接
红豌豆

3
这个dev依存关系如何?该应用是否不需要mv才能正常运行?
jgr0

17

util.pump 在节点0.10中弃用并生成警告消息

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

因此,使用流复制文件的解决方案是:

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 */ });

2
这是复制/移动两个不同分区上的文件的正确方法。谢谢!
slickplaid

9

使用重命名功能:

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

哪里

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

假设您要保持文件名不变。


4
请注意,如果您尝试在不同分区之间重命名文件,无论是在某些虚拟文件系统(例如
docker

8

fs-extra模块允许您使用其move()方法来执行此操作。我已经实现了它,并且如果您想将文件从一个目录完全移动到另一个目录(即。从源目录中删除文件。应该适用于大多数基本情况。

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!")
})

5

这是一个使用util.pump的示例,来自>> 如何将文件a移动到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');
});

20
值得注意的是,仅在跨卷移动文件时才需要这样做。否则,您只能使用fs.rename()(在卷中重命名文件并移动它是同一件事)。
2011年

4
util.pump已过时。
andrewrk


可以将文件从本地计算机移动到服务器吗?
绿巨人1991年

不,您需要使用其他方式(例如使用FTP,HTTP或其他协议)。
alessioalex

4

对大于8.0.0的Node版本使用Promise:

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();

3
fs.rename如果您在具有卷的Docker环境中,仅需小心一点就行不通。
Atul Yadav

asyncmoveThem函数添加一个声明。
H_I

3

上面答案中所述,只是我的2美分:copy()方法不能原样用于未经稍作调整即可复制文件:

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);
}

复制函数包装在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);
  })

但是,请记住,如果目标文件夹不存在,文件系统可能会崩溃。


3

我将所有涉及的功能(即rename,)彼此分开copyunlink以获取灵活性并实现所有功能,当然:

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 只是一个便捷函数,例如,当我们需要更细粒度的异常处理时,我们可以单独应用函数。


2

Shelljs是一个非常方便的解决方案。

命令:mv([options,]源,目标)

可用选项:

-f:强制(默认行为)

-n:防止覆盖

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!');

1

这是对teoman shipahi的回答的重新表达,其名称略有歧义,并遵循在尝试调用代码之前定义代码的设计原则。(虽然节点允许您执行其他操作,但是将手推车放在马前不是一个好习惯。)

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();
        }
    );
}

0

借助以下URL的帮助,您可以将文件CURRENT Source复制或移动到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 *********/



-6

您可以使用move-filenpm软件包:

首先安装软件包:

$ npm install move-file

用法:

const moveFile = require('move-file');

// moveFile Returns a Promise that resolves when the file has been moved
moveFile('source/unicorn.png', 'destination/unicorn.png')
  .then(() => {/* Handle success */})
  .catch((err) => {/* Handle failure */});

// Or use async/await
(async () => {
    try {
      await moveFile('source/unicorn.png', 'destination/unicorn.png');
      console.log('The file has been moved');
    } catch (err) {
      // Handle failure
      console.error(err);
    }
})();

简短而明智的回答,好的@paridhishah
Abdullah Pariyani

2
这是对尚未创建的函数的调用,因此只会引发错误。
史蒂夫·凯里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.