Пошук уроків, статей та іншого контенту
Розберіться, як створювати, копіювати, перейменовувати та безпечно видаляти файли.
fsДля роботи з файлами в Node.js використовується вбудований модуль fs — скорочення від file system.
Асинхронний API модуля доступний у варіанті fs/promises. Його методи повертають проміси, тому для роботи з ними зручно використовувати async і await.
Основні операції:
writeFile() — створення або перезапис файлу;
copyFile() — копіювання файлу;
rename() — перейменування або переміщення файлу;
unlink() — видалення файлу.
Підключення модуля:
const fs = require('node:fs/promises');Метод writeFile() записує текст у файл:
await fs.writeFile('notes.txt', 'Перший запис у файлі');Якщо файлу ще немає, Node.js створить його. Якщо файл уже існує, його вміст буде перезаписано.
Щоб додати кодування та явно працювати з текстом, можна передати третій аргумент:
await fs.writeFile(
'notes.txt',
'Текст українською мовою',
'utf8'
);Якщо потрібно створити файл лише тоді, коли його ще немає, використовуйте прапорець wx:
try {
await fs.writeFile('unique.txt', 'Цей файл не можна перезаписати', {
encoding: 'utf8',
flag: 'wx'
});
} catch (error) {
if (error.code === 'EEXIST') {
console.log('Файл уже існує');
} else {
throw error;
}
}Прапорець wx спричинить помилку, якщо файл уже існує.
Для копіювання використовується метод copyFile():
await fs.copyFile('notes.txt', 'notes-copy.txt');Перший аргумент — шлях до початкового файлу, другий — шлях до копії.
За замовчуванням, якщо файл призначення вже існує, він може бути перезаписаний. Щоб заборонити перезапис, використовуйте COPYFILE_EXCL:
const mode = fs.constants.COPYFILE_EXCL;
await fs.copyFile('notes.txt', 'notes-copy.txt', mode);У такому разі операція завершиться помилкою, якщо notes-copy.txt уже існує.
Метод rename() змінює назву файлу:
await fs.rename('notes-copy.txt', 'renamed-notes.txt');Цей метод також може перемістити файл в іншу папку:
await fs.rename(
'renamed-notes.txt',
'archive/renamed-notes.txt'
);Папка archive повинна існувати заздалегідь. Для створення папки використовується mkdir():
await fs.mkdir('archive', { recursive: true });Параметр recursive: true також створить батьківські папки, якщо їх немає.
Для видалення файлу використовується unlink():
await fs.unlink('notes.txt');Метод видаляє саме файл. Якщо вказаного файлу немає, Node.js поверне помилку.
try {
await fs.unlink('notes.txt');
console.log('Файл видалено');
} catch (error) {
if (error.code === 'ENOENT') {
console.log('Файл не знайдено');
} else {
throw error;
}
}Перед видаленням важливого файлу варто:
перевірити, що шлях належить потрібній робочій папці;
перевірити, що об’єкт існує;
перевірити, що це саме файл, а не папка;
видаляти лише очікуваний файл.
Ось функція, яка видаляє тільки файл усередині визначеної робочої папки:
const fs = require('node:fs/promises');
const path = require('node:path');
async function safeDeleteFile(workspace, filePath) {
const workspacePath = path.resolve(workspace);
const targetPath = path.resolve(filePath);
const relativePath = path.relative(workspacePath, targetPath);
// Забороняємо видалення за межами робочої папки
if (
relativePath.startsWith('..' + path.sep) ||
path.isAbsolute(relativePath)
) {
throw new Error('Шлях до файлу виходить за межі робочої папки');
}
const fileInfo = await fs.lstat(targetPath);
// Не дозволяємо видаляти папки
if (!fileInfo.isFile()) {
throw new Error('Вказаний шлях не є звичайним файлом');
}
await fs.unlink(targetPath);
}
async function main() {
await safeDeleteFile('./workspace', './workspace/temporary.txt');
console.log('Файл безпечно видалено');
}
main().catch((error) => {
console.error('Помилка:', error.message);
});path.resolve() перетворює відносний шлях на абсолютний, а path.relative() допомагає перевірити, чи не виходить цільовий файл за межі робочої папки.
Наступна програма:
створює робочу папку;
створює файл;
копіює його;
перейменовує копію;
безпечно видаляє перейменований файл.
Збережіть код у файлі file-operations.js і запустіть командою node file-operations.js.
const fs = require('node:fs/promises');
const path = require('node:path');
const workspace = path.resolve('./file-workspace');
const sourceFile = path.join(workspace, 'original.txt');
const copyFile = path.join(workspace, 'copy.txt');
const renamedFile = path.join(workspace, 'renamed-copy.txt');
async function safeDeleteFile(workspacePath, filePath) {
const workspaceAbsolutePath = path.resolve(workspacePath);
const targetAbsolutePath = path.resolve(filePath);
const relativePath = path.relative(
workspaceAbsolutePath,
targetAbsolutePath
);
// Перевіряємо, що файл розташований у робочій папці
if (
relativePath.startsWith('..' + path.sep) ||
path.isAbsolute(relativePath)
) {
throw new Error('Не можна видаляти файл за межами робочої папки');
}
const fileInfo = await fs.lstat(targetAbsolutePath);
// Перевіряємо, що шлях веде саме до файлу
if (!fileInfo.isFile()) {
throw new Error('Можна видаляти лише звичайні файли');
}
await fs.unlink(targetAbsolutePath);
}
async function main() {
// Створюємо робочу папку, якщо її ще немає
await fs.mkdir(workspace, { recursive: true });
// Створюємо початковий файл
await fs.writeFile(
sourceFile,
'Це вміст початкового файлу.',
'utf8'
);
console.log('Початковий файл створено');
// Створюємо копію
await fs.copyFile(sourceFile, copyFile);
console.log('Файл скопійовано');
// Перейменовуємо копію
await fs.rename(copyFile, renamedFile);
console.log('Копію перейменовано');
// Безпечно видаляємо перейменовану копію
await safeDeleteFile(workspace, renamedFile);
console.log('Перейменовану копію видалено');
}
main().catch((error) => {
console.error('Виникла помилка:', error.message);
});Після виконання програми у папці file-workspace залишиться файл original.txt. Файл renamed-copy.txt буде видалено.
Файлові операції можуть завершитися помилкою. Наприклад:
файл для копіювання не існує;
папка призначення не існує;
немає дозволу на доступ;
файл уже існує, а використовується прапорець wx;
програма намагається видалити папку через unlink().
Для обробки помилок використовуйте try...catch:
const fs = require('node:fs/promises');
async function copyFile() {
try {
await fs.copyFile('source.txt', 'backup.txt');
console.log('Копію створено');
} catch (error) {
if (error.code === 'ENOENT') {
console.error('Початковий файл не знайдено');
} else if (error.code === 'EACCES') {
console.error('Недостатньо прав для роботи з файлом');
} else {
console.error('Невідома помилка:', error.message);
}
}
}
copyFile();Обробляйте лише ті помилки, які можете коректно пояснити або виправити. Інші помилки краще передавати далі або виводити в журнал.
Шляхи на кшталт 'notes.txt' розраховуються від поточної робочої папки, з якої запущено Node.js.
Перевірити її можна так:
console.log(process.cwd());Для побудови надійніших шляхів використовуйте path.join():
const path = require('node:path');
const filePath = path.join('data', 'notes.txt');Цей код не спрацює, якщо папки data немає:
await fs.writeFile('data/notes.txt', 'Текст');Спочатку створіть папку:
await fs.mkdir('data', { recursive: true });
await fs.writeFile('data/notes.txt', 'Текст');Не формуйте шлях для видалення без контролю його значення, особливо якщо частина шляху надходить від користувача.
Перед unlink() перевіряйте, що:
файл належить дозволеній папці;
це не коренева або системна папка;
шлях не містить несподіваних переходів на кшталт ..;
видалення справді потрібне.
unlink()unlink() призначений для файлів. Для папки він поверне помилку. У цьому уроці видаляйте лише файли та перевіряйте тип об’єкта через lstat().
writeFile() створює файл або перезаписує його вміст.
Прапорець wx допомагає створити файл без перезапису наявного.
copyFile() створює копію файлу.
rename() перейменовує або переміщує файл.
unlink() видаляє файл.
mkdir() створює папки, необхідні для роботи з файлами.
Асинхронні операції з fs/promises потрібно виконувати через await.
Потенційно небезпечні операції видалення слід перевіряти та обмежувати дозволеною робочою папкою.