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

yar*_*ar1 25 file-io node.js

如果文件已存在,fs.rename是否会覆盖该文件?

var fs = require('fs'),
    oldPath = 'firstfile.txt',
    newPath = 'temp/firstfile.txt';

fs.rename(oldPath, newPath, function (err) {
    console.log('rename callback ', err); 
});
Run Code Online (Sandbox Code Playgroud)

如果'/newFolder/somefile.txt'存在,会发生什么?

Ila*_*mer 41

简短回答:是的


答案很长:

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

var fs = require('fs');
Run Code Online (Sandbox Code Playgroud)

创建两个文件:

fs.writeFileSync('a.txt',"This is a file")
fs.writeFileSync('b.txt',"This is another file")
Run Code Online (Sandbox Code Playgroud)

改名:

fs.renameSync('a.txt','b.txt');
Run Code Online (Sandbox Code Playgroud)

检查它是否被覆盖:

var text = fs.readFileSync('b.txt', "utf-8");

console.log(text) // This is a file
Run Code Online (Sandbox Code Playgroud)

  • 我想我必须做fs.exists(文件,函数(存在){if(exists){return;} else {fs.rename(...? (6认同)

bin*_*nki 6

nodejs 会fs.rename()覆盖文件,因为这就是 Unixrename()的定义方式,fs.rename()并被记录为包装rename()Unix 系统调用。我不知道 nodejs 文档中有任何地方直接说明了这一点fs.rename()。但是,有一些事情需要注意,让我们确定这一点:

  1. nodejs 文档链接到 Linux 联机帮助页,用于rename(2) 描述fs.rename. GitHub的永久链接的文档并不linkify,但之处理自动开启rename(2)进入rename(2)

  2. 文件的“系统调用和手册页”一节指出,系统调用模拟在Windows上的UNIX行为。我从“有时不可能在 Windows 上替换 Unix 系统调用语义”这句话推断出这一点,这意味着nodejs 已经在可能的情况下在 Windows 上实现了 Unix 语义

    大多数 Unix 系统调用具有 Windows 等效项,但相对于 Linux 和 macOS,Windows 上的行为可能有所不同。有关有时无法在 Windows 上替换 Unix 系统调用语义的微妙方式的示例,请参阅节点问题 4760

  3. 我看过其他关于此类事情的讨论,人们总是提到 nodejs 如何只使用 libuv 来处理事情,所以人们应该看看 libuv。libuv 的目标是提供 POSIX API 的可移植异步实现,因此其目标之一是即使在 Windows 上也能像 unix 一样运行。该libuv文档似乎没有商量rename()的长度,但Windows实现的fs__rename()呼叫MoveFileEx()MOVEFILE_REPLACE_EXISTING

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

    如果new参数命名的链接存在,则应将其删除并将旧的重命名为new。在这种情况下,在整个重命名操作期间,名为new的链接应该对其他线程保持可见,并在操作开始之前引用由newold引用的文件。

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

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

注:由于便携性的问题,这是好事,可以考虑使用便携助手像graceful-fscross-spawn当你想你的代码也工作于Windows用户。我意识到这不是提问者的问题,但我推断提问者只会问这样的问题,因为在 win32 背景下,重命名不能覆盖文件,或者因为只有当对 Unix 以外的可移植性感兴趣时才会问这样的问题.