Пошук уроків, статей та іншого контенту
Навчіться створювати, читати, перейменовувати й видаляти директорії та перевіряти їхній стан.
У Node.js операції з файловою системою доступні через модуль node:fs. Для асинхронної роботи з Promise використовуйте node:fs/promises:
import * as fs from 'node:fs/promises';Основні операції з директоріями:
створення — mkdir;
readdirперейменування або переміщення — rename;
видалення — rm;
перевірка стану — stat або lstat.
Шляхи краще будувати за допомогою модуля node:path, а не конкатенацією рядків:
import path from 'node:path';
const logsDirectory = path.join(process.cwd(), 'logs');Такий код коректно працює на різних операційних системах.
Для створення директорії використовується mkdir:
await fs.mkdir('reports');Якщо директорія вже існує, за замовчуванням Node.js поверне помилку EEXIST.
Опція recursive: true дозволяє створити всю структуру шляху:
await fs.mkdir('data/2026/january', { recursive: true });У цьому випадку Node.js створить:
data;
data/2026;
data/2026/january.
Якщо такі директорії вже існують, помилки не буде. Це зручно для підготовки робочих каталогів перед виконанням програми.
const directory = path.join(process.cwd(), 'storage', 'uploads');
await fs.mkdir(directory, { recursive: true });Метод readdir повертає масив імен елементів директорії:
const entries = await fs.readdir('./storage');
console.log(entries);Результат може виглядати так:
[ 'uploads', 'config.json', 'archive' ]За замовчуванням результат не містить інформації про тип елемента. Щоб отримати об'єкти Dirent з методами isDirectory() та isFile(), передайте withFileTypes: true:
const entries = await fs.readdir('./storage', {
withFileTypes: true
});
for (const entry of entries) {
if (entry.isDirectory()) {
console.log(`Директорія: ${entry.name}`);
} else if (entry.isFile()) {
console.log(`Файл: ${entry.name}`);
}
}Цей варіант зручний, коли потрібно відфільтрувати лише директорії:
const entries = await fs.readdir('./storage', {
withFileTypes: true
});
const directories = entries
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name);
console.log(directories);readdir читає лише безпосередній вміст директорії. Він не обходить автоматично всі вкладені рівні.
Для перейменування використовується rename:
await fs.rename('drafts', 'published');Метод також може перемістити директорію в інше місце:
await fs.rename(
'./temporary/reports',
'./archive/reports'
);Батьківська директорія призначення ./archive вже повинна існувати. rename не створює її автоматично.
Шляхи до директорії призначення можна будувати через path.join:
const source = path.join(process.cwd(), 'temporary', 'reports');
const destination = path.join(process.cwd(), 'archive', 'reports');
await fs.rename(source, destination);Поведінка, якщо директорія призначення вже існує, може залежати від операційної системи. Тому перед переміщенням важливих даних варто перевірити стан призначення або обробити помилку.
Метод stat повертає інформацію про файл або директорію:
const information = await fs.stat('./storage');
console.log(information.isDirectory());
console.log(information.isFile());Для перевірки існування шляху зазвичай викликають stat і обробляють помилку ENOENT:
async function getPathState(targetPath) {
try {
const information = await fs.stat(targetPath);
return {
exists: true,
isDirectory: information.isDirectory(),
isFile: information.isFile()
};
} catch (error) {
if (error.code === 'ENOENT') {
return {
exists: false,
isDirectory: false,
isFile: false
};
}
throw error;
}
}Використання:
const state = await getPathState('./storage');
if (!state.exists) {
console.log('Директорії не існує');
} else if (state.isDirectory) {
console.log('Шлях вказує на директорію');
} else {
console.log('Шлях існує, але це не директорія');
}stat також може завершитися помилкою через відсутність прав доступу або іншу проблему. Не варто перетворювати будь-яку помилку на стан «шлях не існує» — обробляйте лише очікуваний код ENOENT.
У сучасному Node.js для видалення директорій використовується rm:
await fs.rm('./temporary');Це спрацює, якщо директорія порожня. Для видалення директорії разом із вкладеним вмістом використовуйте recursive: true:
await fs.rm('./temporary', {
recursive: true
});Опція force: true не вважає відсутність шляху помилкою:
await fs.rm('./temporary', {
recursive: true,
force: true
});Такий варіант зручний для очищення тимчасового каталогу:
const temporaryDirectory = path.join(process.cwd(), 'temporary');
await fs.rm(temporaryDirectory, {
recursive: true,
force: true
});Будьте обережні зі шляхами, які передаєте в rm з опцією recursive: true: помилка у формуванні шляху може призвести до видалення не тих даних.
Наведена програма створює вкладені директорії, читає їхній вміст, перевіряє стан, перейменовує директорію та видаляє робочий каталог.
import * as fs from 'node:fs/promises';
import path from 'node:path';
const workspace = path.join(process.cwd(), 'directory-demo');
const sourceDirectory = path.join(workspace, 'reports', 'drafts');
const renamedDirectory = path.join(workspace, 'reports', 'published');
async function getDirectoryState(targetPath) {
try {
const information = await fs.stat(targetPath);
return {
exists: true,
isDirectory: information.isDirectory(),
isFile: information.isFile()
};
} catch (error) {
if (error.code === 'ENOENT') {
return {
exists: false,
isDirectory: false,
isFile: false
};
}
throw error;
}
}
async function main() {
// Видаляємо залишки попереднього запуску прикладу
await fs.rm(workspace, {
recursive: true,
force: true
});
// Створюємо вкладену структуру директорій
await fs.mkdir(sourceDirectory, {
recursive: true
});
console.log('Створено:', sourceDirectory);
// Читаємо вміст батьківської директорії
const reportsDirectory = path.join(workspace, 'reports');
const entries = await fs.readdir(reportsDirectory, {
withFileTypes: true
});
for (const entry of entries) {
const type = entry.isDirectory() ? 'директорія' : 'файл';
console.log(`${entry.name}: ${type}`);
}
// Перевіряємо стан директорії
const beforeRename = await getDirectoryState(sourceDirectory);
console.log('До перейменування:', beforeRename);
// Перейменовуємо директорію
await fs.rename(sourceDirectory, renamedDirectory);
console.log('Перейменовано на:', renamedDirectory);
const afterRename = await getDirectoryState(sourceDirectory);
const renamedState = await getDirectoryState(renamedDirectory);
console.log('Старий шлях:', afterRename);
console.log('Новий шлях:', renamedState);
// Видаляємо всю демонстраційну структуру
await fs.rm(workspace, {
recursive: true,
force: true
});
const afterDelete = await getDirectoryState(workspace);
console.log('Після видалення:', afterDelete);
}
main().catch((error) => {
console.error('Помилка:', error);
process.exitCode = 1;
});Для запуску з синтаксисом import у файлі package.json має бути вказано:
{
"type": "module"
}Або файл можна назвати з розширенням .mjs.
Операції з файловою системою можуть завершитися помилкою. Найпоширеніші коди:
ENOENT — шлях не існує;
EEXIST — елемент із таким іменем уже існує;
ENOTDIR — частина шляху, яка має бути директорією, є файлом;
EACCES — недостатньо прав доступу;
ENOTEMPTY — спроба видалити непорожню директорію без рекурсивного режиму.
Приклад обробки помилки створення:
try {
await fs.mkdir('./reports');
console.log('Директорію створено');
} catch (error) {
if (error.code === 'EEXIST') {
console.log('Директорія вже існує');
} else {
throw error;
}
}Якщо директорія може вже існувати, часто простіше використати:
await fs.mkdir('./reports', { recursive: true });access перед операцієюПослідовність «перевірити, а потім створити або видалити» може бути ненадійною: між цими операціями інший процес може змінити файлову систему.
Краще одразу виконати потрібну операцію та обробити її помилку:
try {
await fs.rm('./temporary', {
recursive: true
});
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}Для простого створення директорії ще зручніше використовувати recursive: true.
recursiveЦей код не спрацює, якщо всередині є файли або вкладені директорії:
await fs.rm('./data');Для повного видалення структури потрібні обидві опції:
await fs.rm('./data', {
recursive: true,
force: true
});rename може перейменувати або перемістити директорію, але не створює відсутні батьківські директорії:
await fs.mkdir('./archive', { recursive: true });
await fs.rename('./reports', './archive/reports');Відносний шлях обчислюється від process.cwd(), тобто від директорії, з якої запущено Node.js, а не обов'язково від директорії файлу програми.
Для передбачуваної поведінки використовуйте абсолютні шляхи або явно додавайте process.cwd():
const directory = path.join(process.cwd(), 'storage');fs.mkdir створює директорії; { recursive: true } створює також відсутні батьківські директорії.
fs.readdir читає безпосередній вміст директорії.
withFileTypes: true дає змогу визначити, чи є елемент файлом або директорією.
fs.rename перейменовує або переміщує директорію.
fs.rm видаляє директорії; { recursive: true } потрібна для непорожніх директорій.
fs.stat дає змогу перевірити існування шляху та визначити його тип.
Для асинхронного коду зручніше використовувати API з node:fs/promises.
Під час видалення з recursive: true потрібно особливо уважно перевіряти сформований шлях.