Пути к файлам (модуль path)

Почему не стоит склеивать пути строками вручную и что предлагает модуль path.

Модуль path — встроенный модуль для построения и разбора путей к файлам с учётом особенностей операционной системы.

Проблема разных ОС

В Unix-системах (Linux, macOS) разделитель путей — прямой слеш /, а в Windows — обратный \. Если склеивать пути вручную через +, код сломается на другой ОС или из-за лишних/недостающих слешей. Модуль path решает это за вас.

path.join — безопасная склейка

Функция join соединяет части пути правильным разделителем и убирает дубли слешей:

const path = require("path");

const full = path.join("src", "utils", "helpers.js");
console.log(full); // на Unix: src/utils/helpers.js

// лишние слеши и .. обрабатываются корректно
console.log(path.join("a/", "/b", "../c")); // a/c

path.resolve — абсолютный путь

resolve строит абсолютный путь от текущей папки. Это надёжнее относительных путей, которые зависят от того, откуда запущена программа:

const path = require("path");

console.log(path.resolve("data", "file.txt"));
// напр. /Users/me/project/data/file.txt

Разбор пути

path умеет и разбирать путь на части:

ФункцияЧто вернёт для /app/index.js
path.basenameindex.js — имя файла
path.dirname/app — папка
path.extname.js — расширение
const path = require("path");
const p = "/app/src/index.js";

console.log(path.basename(p)); // index.js
console.log(path.dirname(p));  // /app/src
console.log(path.extname(p));  // .js

__dirname и __filename

В CommonJS-модулях доступны две полезные переменные: __dirname — путь к папке текущего файла, __filename — путь к самому файлу. С ними строят пути, не зависящие от места запуска:

const path = require("path");

// надёжный путь к файлу рядом с этим скриптом
const configPath = path.join(__dirname, "config.json");
console.log(configPath);

Это частый приём: path.join(__dirname, ...) всегда указывает относительно файла, а не относительно того, откуда запустили node. Разница важна: относительный путь "config.json" Node ищет от текущей рабочей директории — то есть от папки, в которой вы набрали команду. Запустите тот же скрипт из другого места — и относительный путь укажет не туда. А __dirname привязан к самому файлу и не зависит от места запуска. Поэтому для надёжного доступа к файлам рядом со скриптом всегда отталкивайтесь от __dirname.

В ES-модулях переменных __dirname и __filename нет — там путь к текущему файлу получают из import.meta.url. Но идея та же: строить пути относительно расположения файла, а не относительно места запуска.

Разбор расширения — это работа со строкой

Сам по себе разбор имени файла — обычный JavaScript. Вот упрощённый аналог extname:

function getExtension(fileName) {
  const dot = fileName.lastIndexOf(".");
  if (dot <= 0) return ""; // нет точки или скрытый файл
  return fileName.slice(dot);
}

console.log(getExtension("photo.png"));
console.log(getExtension("archive.tar.gz"));
console.log(getExtension("README"));

Вывод:

.png
.gz

Итог

  • Не склеивайте пути вручную через + — используйте path.join.
  • path.resolve строит абсолютный путь, более надёжный.
  • basename, dirname, extname разбирают путь на части.
  • __dirname — папка текущего файла; path.join(__dirname, ...) — частый приём.
Проверьте себя
1. Почему лучше использовать path.join вместо склейки строк через +?
AЭто короче писать
Bpath.join учитывает разделитель ОС и убирает дубли слешей
CСтроки нельзя складывать
Dpath.join работает быстрее в 10 раз
2. Что хранит переменная __dirname?
AИмя текущего файла
BПуть к папке текущего файла
CДомашнюю папку пользователя
DПуть, откуда запущен node
3. Что вернёт path.extname('/app/index.js')?
Aindex.js
B/app
C.js
Djs
Поддержать проект