如果文件已存在,fs.rename是否会覆盖该文件?
var fs = require('fs'),
oldPath = 'firstfile.txt',
newPath = 'temp/firstfile.txt';
fs.rename(oldPath, newPath, function (err) {
console.log('rename callback ', err);
});
如果'/ newFolder/somefile.txt'存在,会发生什么?
答案 0 :(得分:37)
简短回答:是
我创建了一个脚本来检查它:
var fs = require('fs');
创建两个文件:
fs.writeFileSync('a.txt',"This is a file")
fs.writeFileSync('b.txt',"This is another file")
重命名:
fs.renameSync('a.txt','b.txt');
检查是否覆盖:
var text = fs.readFileSync('b.txt', "utf-8");
console.log(text) // This is a file
答案 1 :(得分:3)
nodejs的fs.rename()
会覆盖文件,因为这是定义Unix rename()
的方式,而fs.rename()
被记录为包装rename()
Unix系统调用。我不知道nodejs文档中有关fs.rename()
直接说明这一点的任何地方。但是,有几点需要注意,让我们确定一下:
nodejs docs链接到rename(2)
when describing the functionality of fs.rename
的Linux联机帮助页。文档的GitHub永久链接不会将其链接,但处理程序会自动将rename(2)
转换为rename(2)
。
“Syscalls and man pages” section of documentation表示系统调用在Windows上模拟unix行为。我从“在Windows上替换Unix系统调用语义有时是不可能的”一词中推断出这一点,这意味着 nodejs在可能的情况下在Windows上实现了Unix语义:
大多数Unix系统调用都具有Windows等效功能,但Windows相对于Linux和macOS的行为可能有所不同。有关在Windows上有时无法替换Unix系统调用语义的微妙方法的示例,请参阅Node issue 4760。
我已经看到过关于这样的事情的其他讨论,人们总是提到nodejs如何使用libuv做事情,所以我们应该只看一下libuv。 libuv的目标是提供POSIX API的可移植异步实现,因此其目标之一就是在Windows上表现得像unix一样。 libuv文档似乎不会详细讨论rename()
,而是 the Windows implementation of fs__rename()
调用MoveFileEx()
with MOVEFILE_REPLACE_EXISTING
。
哦,我差点忘了。即使您知道nodejs将fs.rename()
定义为POSIX rename()
,也许您不知道有关覆盖的POSIX-defined behavior rename()
:
如果 new 参数指定的链接存在,则应将其删除,并将旧重命名为 new 。在这种情况下,名为 new 的链接在整个重命名操作中应对其他线程保持可见,并引用 new 或 old 在手术开始之前。
简单地说,如果重命名的目标已经存在,则描述了事务文件替换。如果在调用rename()
之前已经存在具有新名称的文件,它将永远不会存在 - 即使您的程序崩溃或盒子断电。在某个时间点,新名称将开始引用具有旧名称的文件。
您应该更喜欢这种方法而不是删除原始文件,然后重命名新创建的文件,因为新路径上的文件将暂时不再存在(可能会导致试图打开它的某种竞争条件),或者,如果过程被终止或在正确的时间发生停电。
注意:由于可移植性问题,当您希望代码也适用于Windows用户时,最好考虑使用graceful-fs
和cross-spawn
等可移植性帮助程序。我意识到这不是提问者的问题,但是我推断提问者只会问这样一个问题,因为win32背景,重命名不能覆盖文件,或者因为人们对Unix之外的可移植性感兴趣时只会问这样的问题的
答案 2 :(得分:1)
看起来fr.rename提供的功能与Linux rename(2)命令提供的功能相同(来源:Move File in ExpressJS/NodeJS)。话虽如此,如果你查看Linux rename(2)命令的文档,他们会说如果你重命名的文件名已经存在,现有的文件名将被替换和覆盖(来源:http://linux.die.net/man/2/rename)