【发布时间】:2012-01-24 15:06:28
【问题描述】:
如何在 node.js 上移动文件(如 mv 命令外壳)?有什么方法吗?或者我应该读取文件,写入新文件并删除旧文件?
【问题讨论】:
如何在 node.js 上移动文件(如 mv 命令外壳)?有什么方法吗?或者我应该读取文件,写入新文件并删除旧文件?
【问题讨论】:
根据 seppo0010 的评论,我使用了重命名功能来做到这一点。
http://nodejs.org/docs/latest/api/fs.html#fs_fs_rename_oldpath_newpath_callback
fs.rename(oldPath, newPath, callback)
添加于:v0.0.2
oldPath <String> | <Buffer> newPath <String> | <Buffer> callback <Function>异步重命名(2)。除了可能的例外,没有其他参数 给完成回调。
【讨论】:
原生使用 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 ")
【讨论】:
本例取自:Node.js in Action
一个 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);
}
}
【讨论】:
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 */ });
【讨论】:
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!")
})
【讨论】:
对高于 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();
【讨论】:
fs.rename 在带有卷的 Docker 环境中不起作用。
async 声明添加到moveThem 函数。
const { promises } = require("fs"),然后使用promises.rename(那时不需要util)
使用重命名功能:
fs.rename(getFileName, __dirname + '/new_folder/' + getFileName);
在哪里
getFilename = file.extension (old path)
__dirname + '/new_folder/' + getFileName
假设您希望保持文件名不变。
【讨论】:
这是一个使用 util.pump 的示例,来自 >> 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');
});
【讨论】:
fs.rename()(在卷中重命名文件和移动它是一回事)。
正如answer above 中所述,只需我的 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);
})
但是,请记住,如果目标文件夹不存在,文件系统可能会崩溃。
【讨论】:
我会将所有涉及的功能(即rename、copy、unlink)彼此分开,以获得灵活性并承诺一切,当然:
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 只是一个便利函数,我们可以单独应用这些函数,例如,当我们需要更细粒度的异常处理时。
【讨论】:
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!');
【讨论】:
这是teoman shipahi's answer 的重新散列,名称稍微不那么含糊,并遵循在尝试调用它之前定义代码的设计原则。 (虽然节点允许您做其他事情,但本末倒置并不是一个好习惯。)
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();
}
);
}
【讨论】:
借助以下 URL,您可以将文件当前源复制或移动到目标源
/*********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 *********/
【讨论】:
如果您尝试移动或重命名 node.js 源文件,请尝试此https://github.com/viruschidai/node-mv。它将更新所有其他文件中对该文件的引用。
【讨论】:
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')
【讨论】: