Node.jsМодуль 3: Файловая система
Работа с директориями
Создание, удаление и обход директорий
Цель урока
В этом уроке ты научишься:
- Создавать и удалять директории
- Читать содержимое директорий
- Рекурсивно обходить файловую систему
Создание директорий
Одна директория
const fs = require('fs/promises');
await fs.mkdir('new-folder');Вложенные директории
// recursive: true создаёт все промежуточные папки
await fs.mkdir('path/to/deep/folder', { recursive: true });С проверкой существования
async function ensureDir(dir) {
try {
await fs.mkdir(dir, { recursive: true });
} catch (error) {
if (error.code !== 'EEXIST') throw error;
}
}Удаление директорий
Пустая директория
await fs.rmdir('empty-folder');Директория с содержимым
// Node.js 14.14+
await fs.rm('folder', { recursive: true, force: true });
// force: true не выбрасывает ошибку если папки нетЧтение содержимого
Простой список
const files = await fs.readdir('folder');
console.log(files); // ['file1.txt', 'file2.txt', 'subfolder']С информацией о типе
const entries = await fs.readdir('folder', { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile()) {
console.log('Файл:', entry.name);
} else if (entry.isDirectory()) {
console.log('Папка:', entry.name);
}
}Рекурсивный обход
Все файлы
const fs = require('fs/promises');
const path = require('path');
async function getAllFiles(dir) {
const files = [];
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...await getAllFiles(fullPath));
} else {
files.push(fullPath);
}
}
return files;
}
const allFiles = await getAllFiles('./src');
console.log(allFiles);С фильтрацией
async function getFilesByExtension(dir, ext) {
const files = await getAllFiles(dir);
return files.filter(file => path.extname(file) === ext);
}
const jsFiles = await getFilesByExtension('./src', '.js');Генератор (эффективно по памяти)
async function* walkDir(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
yield* walkDir(fullPath);
} else {
yield fullPath;
}
}
}
// Использование
for await (const file of walkDir('./src')) {
console.log(file);
}Наблюдение за изменениями
const fs = require('fs');
const watcher = fs.watch('folder', { recursive: true }, (eventType, filename) => {
console.log(`${eventType}: ${filename}`);
});
// Остановка наблюдения
watcher.close();chokidar (рекомендуется)
npm install chokidarconst chokidar = require('chokidar');
const watcher = chokidar.watch('src', {
ignored: /node_modules/,
persistent: true
});
watcher
.on('add', path => console.log(`Добавлен: ${path}`))
.on('change', path => console.log(`Изменён: ${path}`))
.on('unlink', path => console.log(`Удалён: ${path}`));Практические примеры
Копирование директории
async function copyDir(src, dest) {
await fs.mkdir(dest, { recursive: true });
const entries = await fs.readdir(src, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
await copyDir(srcPath, destPath);
} else {
await fs.copyFile(srcPath, destPath);
}
}
}Размер директории
async function getDirSize(dir) {
let size = 0;
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
size += await getDirSize(fullPath);
} else {
const stats = await fs.stat(fullPath);
size += stats.size;
}
}
return size;
}
const size = await getDirSize('./node_modules');
console.log(`Размер: ${Math.round(size / 1024 / 1024)} MB`);Практика
Задание 1: Список файлов
Задача: Выведи все .js файлы в директории.
Решение:
const fs = require('fs/promises');
const path = require('path');
async function listJsFiles(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile() && path.extname(entry.name) === '.js') {
console.log(entry.name);
}
}
}Задание 2: Очистка директории
Задача: Удали все файлы в директории, но оставь папки.
Решение:
async function clearFiles(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isFile()) {
await fs.unlink(path.join(dir, entry.name));
}
}
}Проверь себя
- Как создать вложенные директории?
- Как удалить директорию с содержимым?
- Что возвращает
readdirсwithFileTypes: true?