node js:fs.rename覆盖文件(如果已存在)

时间:2014-01-19 15:56:18

标签: node.js file-io

如果文件已存在,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'存在,会发生什么?

3 个答案:

答案 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()直接说明这一点的任何地方。但是,有几点需要注意,让我们确定一下:

  1. nodejs docs链接到rename(2) when describing the functionality of fs.rename的Linux联机帮助页。文档的GitHub永久链接不会将其链接,但处理程序会自动将rename(2)转换为rename(2)

  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

  3. 我已经看到过关于这样的事情的其他讨论,人们总是提到nodejs如何使用libuv做事情,所以我们应该只看一下libuv。 libuv的目标是提供POSIX API的可移植异步实现,因此其目标之一就是在Windows上表现得像unix一样。 libuv文档似乎不会详细讨论rename(),而是 the Windows implementation of fs__rename()调用MoveFileEx() with MOVEFILE_REPLACE_EXISTING

  4. 哦,我差点忘了。即使您知道nodejs将fs.rename()定义为POSIX rename(),也许您不知道有关覆盖的POSIX-defined behavior rename()

      

    如果 new 参数指定的链接存在,则应将其删除,并将重命名为 new 。在这种情况下,名为 new 的链接在整个重命名操作中应对其他线程保持可见,并引用 new old 在手术开始之前。

    简单地说,如果重命名的目标已经存在,则描述了事务文件替换。如果在调用rename()之前已经存在具有新名称的文件,它将永远不会存在 - 即使您的程序崩溃或盒子断电。在某个时间点,新名称将开始引用具有旧名称的文件。

    您应该更喜欢这种方法而不是删除原始文件,然后重命名新创建的文件,因为新路径上的文件将暂时不再存在(可能会导致试图打开它的某种竞争条件),或者,如果过程被终止或在正确的时间发生停电。

  5. 注意:由于可移植性问题,当您希望代码也适用于Windows用户时,最好考虑使用graceful-fscross-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