NodeJS - Как скопировать одну папку в другую, переписав только файлы, которые отличаются?
Вопрос:
Как скопировать одну папку в другую в NodeJS, перезаписывая только файлы, которые отличаются?
О методе fs-extra "copy":
Похоже, что метод копирования из fs-extra не имеет возможности пропустить идентичные файлы (которые не были изменены).
Здесь overwrite
опция, но она дает вам возможность перезаписывать только во всех случаях, даже если файлы идентичны, или не перезаписывать, даже если файлы различаются.
3 ответа
Я нашел https://github.com/mattijs/node-rsync и jedrichards /rsyncwrapper, которые хорошо работают и работают в Linux/Windows/etc.
Для простоты и свободы выбора я решил придерживаться второго варианта.
Примеры (в файле readme описаны другие параметры)
Отдельный файл:
rsync({
src: "file.txt",
dest: "tmp/file.txt"
},function (error,stdout,stderr,cmd) {
if ( error ) {
// failed
console.log(error.message);
} else {
// success
}
});
Полный каталог:
rsync({
src: "src-folder/",
dest: "dest-folder",
recursive: true,
exclude: ["*.txt"]
},function (error,stdout,stderr,cmd) {
if ( error ) {
// failed
console.log(error.message);
} else {
// success
}
});
Я создал библиотеку nodejs с открытым исходным кодом под названием Reflect - https://github.com/alumna/reflect
Я был недоволен тем фактом, что обе библиотеки, о которых я упоминал ранее, зависят от команды rsync, что не является многоплатформенным решением, поскольку Windows не предоставляет rsync изначально.
Я сделал Reflect на чистом javascript, чтобы решить эту проблему, без зависимости от rsync или какой-либо другой библиотеки, что делает его подходящим для всех операционных систем.
Просто примечание: Reflect сравнивает файлы аналогично rsync и синхронизирует только разницу между двумя папками, полностью избегая копирования немодифицированных файлов (или измененных, но все еще идентичных файлов), но он по-прежнему не подходит для проектов с большими файлами, поскольку он копирует весь файл, если он отличается.
Установить
$ npm install @alumna/reflect
Применение
import reflect from '@alumna/reflect';
let { res, err } = await reflect({
src: 'src/',
dest: 'dest/',
// (OPTIONAL) Default to 'true'
recursive: true,
// (OPTIONAL) Default to 'true'
// Delete in dest the non-existent files in src
delete: true,
// (OPTIONAL)
// Array with files and folders not to reflect
exclude: [ "skip-this-file.txt", "skip/this/directory" ]
});
if ( err )
console.error( err )
else
console.log( res ) // Directory "src/" reflected to "dest/"
Я бы уточнил здесь различие между действиями «копировать/объединить папку» и «синхронизировать/отражать папку».
В случае двух случайных папок невозможно узнать, являются ли два файла одинаковыми, не читая их содержимое, такие вещи, как время изменения и размер файла, могут быть одинаковыми по совпадению. Вот почему
Если две папки предназначены для того, чтобы быть их зеркалами, то вы можете быть более оптимистичными в отношении состояния мира внутри них и ускорить процесс, сравнив время изменения файлов и скопировав только те, которые изменились недавно. Но все же по замыслу это решение не может быть на 100% пуленепробиваемым. Просто чтобы вы знали :)