节点js:fs.rename覆盖文件,如果已经存在

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”存在,会发生什么情况?

简短的回答: 是的


很长的回答:

我创build了一个脚本来检查它:

 var fs = require('fs'); 

创build两个文件:

 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 

看起来像fr.rename提供了与Linux rename(2)命令提供的function相同的function(来源: 在ExpressJS / NodeJS中移动文件 )。 话虽如此,如果您查看Linux rename(2)命令的文档,他们会说如果您正在重命名的文件名已经存在,那么现有的文件名将被replace并覆盖(来源: http:// linux。 die.net/man/2/rename )

nodejs的fs.rename()覆盖了文件,因为这是Unix rename()定义的方式,而fs.rename()被logging为包装rename() Unix syscall。 我不知道在nodejs文档中的任何地方,直接说明这与fs.rename() 。 但是,有几件事要注意让我们确定这一点:

  1. 在描述fs.rename的function时 ,nodejs文档链接到Linux手册页以rename(2) 。 文档的GitHub固定链接不链接,但处理器会自动将rename(2) rename(2)

  2. 文档的“系统调用和手册页”部分指出,系统调用在Windows上模拟unix行为。 我从“在Windows上replaceUnix系统调用语义有时是不可能的”这个推断,这意味着在可能的情况下nodejs在Windows上实现了Unix语义

    大多数Unix系统调用都具有与Windows相同的function,但是相对于Linux和MacOS,Windows的行为可能会有所不同。 有关在Windows上更换Unix系统调用语义的细微方法的示例,请参阅节点问题4760 。

  3. 我已经看到了关于这种事情的其他讨论,人们总是提到nodejs是如何使用libuv来处理事情的,所以我们只需要看看libuv。 libuv的目标是提供一个可移植的POSIX APIasynchronous实现,因此它的目标之一就是即使在Windows上也像unix一样运行。 libuv文档似乎没有详细讨论rename() ,但fs__rename()的Windows实现 使用MOVEFILE_REPLACE_EXISTING调用MoveFileEx()

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

    如果存在由参数命名的链接,则该链接将被删除, 旧的名称将重命名为新的 。 在这种情况下,一个名为new的链接在整个重命名操作中对其他线程都是可见的,并且在操作开始之前引用newold引用的文件。

    简单地说,如果重命名的目标已经存在,这就描述了事务性文件replace。 如果在调用rename()之前已经存在一个具有新名字的文件,它将永远不会停止存在 – 即使程序崩溃或者电源掉电了。 在某个时间点,新名称将开始引用具有旧名称的文件。

    您应该更喜欢这种方法来删除原始文件,然后重新命名新创build的文件,因为那么新path中的文件将暂时停止存在(可能导致尝试打开它的某个竞争条件),或者如果进程被终止或者在合适的时间发生电力故障,永久性的。

注意:由于可移植性问题,当您希望代码也适用于Windows用户时,考虑使用像graceful-fs这样的可移植助手和cross-spawn是很好的做法。 我意识到这不是提问者的问题,但是我推断提问者只会提出这样一个问题,因为win32背景下重命名不能覆盖文件,或者因为只有在对Unix以外的可移植性感兴趣时才会问这样的问题。