Node 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'?
Ответы
Ответ 1
Короткий ответ: да
Длинный ответ:
Я создал script, чтобы проверить его:
var fs = require('fs');
Создайте два файла:
fs.writeFileSync('a.txt',"This is a file")
fs.writeFileSync('b.txt',"This is another file")
Rename:
fs.renameSync('a.txt','b.txt');
Проверьте, не было ли это превышено:
var text = fs.readFileSync('b.txt', "utf-8");
console.log(text) // This is a file
Ответ 2
Похоже, что fr.rename предоставляет ту же функциональность, что и команда rename (2) Linux (источник: Переместить файл в ExpressJS/NodeJS). Сказав это, если вы посмотрите на документы для команды rename (2), они говорят, что если имя файла, которое вы переименовываете, уже существует, существующее имя файла будет заменено и перезаписано (source: http://linux.die.net/man/2/rename)
Ответ 3
nodejss fs.rename()
перезаписывает файлы, потому что именно так определяется Unix rename()
, а fs.rename()
документируется как обертка syscall rename()
Unix. Я не знаю ни одного места в документах nodejs, которые прямо указывают это на fs.rename()
. Однако есть несколько замечаний, которые позволяют нам это определить:
-
Документы nodejs ссылаются на man-страницу Linux для rename(2)
при описании функциональности fs.rename
. Постоянная ссылка GitHub на документы не связывает его, но процессинг автоматически превращает rename(2)
в rename(2)
.
-
В разделе "Syscalls and man pages" документации указано, что syscalls эмулирует поведение unix в Windows. Я выхожу из фразы "иногда невозможно заменить семантику sysall для Unix в Windows" , что подразумевает, что nodejs внедрил семантику Unix в Windows, когда это возможно:
Большинство системных вызовов Unix имеют эквиваленты Windows, но поведение может отличаться в Windows относительно Linux и macOS. Для примера тонких способов, с помощью которых иногда невозможно заменить семантику sysall для Unix в Windows, см. Node issue 4760.
-
Я видел другие дискуссии о таких вещах, и люди всегда ссылаются на то, как nodejs просто использует libuv для вещей, поэтому нужно просто взглянуть на libuv. Цель libuvs - предоставить переносимую асинхронную реализацию POSIX API, и, таким образом, одна из ее целей - вести себя как unix даже в Windows. В libuv docs не обсуждается rename()
, но реализация Windows fs__rename()
вызывает MoveFileEx()
с MOVEFILE_REPLACE_EXISTING
.
-
О, и я почти забыл. Даже если вы знаете, что nodejs определяет fs.rename()
как POSIX rename()
, возможно, вы не знаете поведение, определяемое POSIX rename()
относительно перезаписи
Если ссылка, названная новым аргументом, существует, она должна быть удалена и переименована в новую. В этом случае ссылка с именем new должна оставаться видимой для других потоков во время операции переименования и ссылаться либо на файл, который был указан новым или старым до начала операции.
Просто это описывает замену транзакционного файла, если цель переименования уже существует. Если файл с новым именем уже существует до вызова rename()
, он никогда не перестанет существовать, даже если ваша программа выйдет из строя или поле потеряет питание. В некоторый момент времени новое имя начнет ссылаться на файл со старым именем.
Вы должны предпочесть этот метод для удаления исходного файла и последующего переименования вновь созданного, потому что файл на новом пути перестанет существовать на мгновение (возможно, вызвав условие гонки для чего-то, пытающегося его открыть) или, если процесс уничтожается или сбой питания происходит в нужное время, навсегда.
Примечание: из-за проблем с переносимостью полезно рассмотреть использование помощников переносимости, таких как graceful-fs
и cross-spawn
, когда вы хотите, чтобы ваш код также работал для пользователей Windows. Я понимаю, что это не вопрос адеектов, но я предположил, что искатель задал бы такой вопрос только из-за фона win32, где переименовать кант перезаписывать файлы или потому, что он задал бы такой вопрос, только если он заинтересован в переносимости за пределами Unix.