源本科技 | 码上会

Node.js 内置模块 path

2026/04/10
1
0

引言

Node.js 内置模块 path 专门用于处理文件路径,提供了一系列标准化的工具函数。它可以自动适配 Windows、macOS、Linux 等不同操作系统的路径分隔符差异,安全地完成路径拼接、解析、规范化、提取信息等操作。 结合上一节学习的 fs 文件系统模块,path 模块能彻底解决跨平台路径报错问题,是 Node.js 开发中处理文件的必备工具。

模块导入

path 是 Node.js 内置核心模块,无需安装,直接导入即可使用,支持两种模块化规范:

// 1. CommonJS 规范(Node.js 默认使用)
const path = require('path');

// 2. ES Module 规范(现代前端推荐)
import path from 'path';

核心全局变量

在路径操作中,两个全局变量是基础:

  • __dirname:获取当前文件所在的目录的绝对路径

  • __filename:获取当前文件的绝对路径


path.join

path.join()最常用的路径拼接方法,它会根据操作系统自动匹配路径分隔符(Windows \,macOS/Linux /),并规范化路径。

语法

path.join([path1, path2, ...pathN])

核心特性

  • 接收任意个路径片段作为参数

  • 自动处理 ./../、多余分隔符等异常格式

  • 不会强制生成绝对路径,依赖传入的路径片段

示例

const path = require('path');

// 拼接当前目录 + files 文件夹 + test.txt
const fullPath = path.join(__dirname, 'files', 'test1.txt');
console.log(fullPath);

// 自动解析 ../ 上层目录
const testPath = path.join('/a', '/b/c', '../', 'd');
// 结果:/a/b/d

重要规范:所有路径拼接操作,禁止使用 + 直接拼接字符串,必须使用 path.join(),避免跨平台报错。


path.resolve

path.resolve() 用于将路径片段解析为绝对路径,相当于在命令行中逐层执行 cd 命令。

语法

path.resolve([from ...], to)

核心特性

  • 最终一定返回绝对路径

  • 从右向左拼接参数,直到拼接成绝对路径为止

  • 无参数时,返回当前工作目录

示例

const path = require('path');

// 生成绝对路径
const absolutePath = path.resolve(__dirname, 'test1.txt');

// 对比演示
console.log(path.join('/a', '/b', 'c'));  // /a/b/c
console.log(path.resolve('/a', '/b', 'c')); // /b/c

path.join 与 path.resolve

特性

path.join

path.resolve

输出结果

拼接后的路径(可相对 / 可绝对)

绝对路径

处理逻辑

单纯拼接 + 规范化

模拟 cd 命令生成绝对路径

适用场景

通用路径拼接

需要绝对路径的场景


path.normalize

path.normalize() 用于规范化路径,自动解析 ..(上层目录)、.(当前目录),并清理多余的路径分隔符。

语法

path.normalize(path)

示例

const path = require('path');

// Windows 系统需转义反斜杠
const rawPath = 'C:\\Users\\Workspaces\\..\\NodeJS\\test1.txt';
const normalizedPath = path.normalize(rawPath);
// 输出:C:\Users\NodeJS\test1.txt

path.basename

path.basename() 获取路径的最后一部分(文件名),支持过滤文件扩展名。

语法

path.basename(path[, ext])
  • path:必填,目标路径字符串

  • ext:可选,要剔除的文件扩展名

示例

const path = require('path');
const filePath = path.join(__dirname, 'files', 'test1.txt');

// 带扩展名
console.log(path.basename(filePath)); // test1.txt
// 不带扩展名
console.log(path.basename(filePath, '.txt')); // test1

path.dirname

path.dirname() 获取路径中的目录部分(不包含文件名)。

语法

path.dirname(path)

示例

const path = require('path');
const filePath = path.join(__dirname, 'files', 'test1.txt');

// 获取文件所在目录
console.log(path.dirname(filePath)); 

path.extname

path.extname() 获取路径中的文件扩展名(包含 .)。

语法

path.extname(path)

示例

const path = require('path');
const filePath = path.join(__dirname, 'files', 'test1.txt');

console.log(path.extname(filePath)); // .txt

path.isAbsolute

path.isAbsolute() 判断一个路径是否为绝对路径,返回布尔值。

语法

path.isAbsolute(path)

示例

const path = require('path');

// 绝对路径
console.log(path.isAbsolute('/files/test1.txt')); // true
// 相对路径
console.log(path.isAbsolute('files/test1.txt')); // false

拓展方法

path.parse

将路径字符串解析为路径对象,包含目录、文件名、扩展名等信息。

const path = require('path');
const info = path.parse('/user/files/test.txt');
/*
{
  root: '/',
  dir: '/user/files',
  base: 'test.txt',
  ext: '.txt',
  name: 'test'
}
*/

path.format

将路径对象反向生成路径字符串,与 path.parse 互为逆操作。

path.format({
  dir: '/user/files',
  base: 'test.txt'
});
// /user/files/test.txt

跨平台分隔符常量

  • path.sep:获取系统默认路径分隔符

  • path.delimiter:获取系统环境变量分隔符

console.log(path.sep); // Windows \ ,macOS /

综合案例

将 HTML 文件中的内联 <style><script> 内容提取出来,生成独立的 .css.js 文件,实现代码分离。

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>时钟</title>
  <style>
    html,
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      background-image: linear-gradient(to bottom right, red, gold);
    }

    .box {
      width: 400px;
      height: 250px;
      background-color: rgba(255, 255, 255, 0.6);
      border-radius: 6px;
      position: absolute;
      left: 50%;
      top: 40%;
      transform: translate(-50%, -50%);
      box-shadow: 1px 1px 10px #fff;
      text-shadow: 0px 1px 30px white;

      display: flex;
      justify-content: space-around;
      align-items: center;
      font-size: 70px;
      user-select: none;
      padding: 0 20px;

      /* 盒子投影 */
      -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0%, transparent), to(rgba(250, 250, 250, .2)));
    }
  </style>
</head>

<body>
  <div class="box">
    <div id="HH">00</div>
    <div>:</div>
    <div id="mm">00</div>
    <div>:</div>
    <div id="ss">00</div>
  </div>

  <script>
    window.onload = function () {
      // 定时器,每隔 1 秒执行 1 次
      setInterval(() => {
        var dt = new Date();
        var HH = dt.getHours();
        var mm = dt.getMinutes();
        var ss = dt.getSeconds();

        // 为页面上的元素赋值
        document.querySelector("#HH").innerHTML = padZero(HH);
        document.querySelector("#mm").innerHTML = padZero(mm);
        document.querySelector("#ss").innerHTML = padZero(ss);
      }, 1000);
    };

    // 补零函数
    function padZero(n) {
      return n > 9 ? n : "0" + n;
    }
  </script>
</body>

</html>

核心需求

  1. 读取 assets/clock.html 文件

  2. 提取 CSS 样式 → 生成 clock/index.css

  3. 提取 JS 代码 → 生成 clock/index.js

  4. 生成新的 HTML 文件,引入外部样式和脚本

文件准备

在项目根目录创建 assets 文件夹,新建 clock.html,写入提供的 HTML 代码。

参考代码

const fs = require('fs');
const path = require('path');

// 1. 定义文件路径
const htmlPath = path.join(__dirname, 'assets', 'clock.html');
const outputDir = path.join(__dirname, 'clock');

// 2. 正则表达式:匹配 style 和 script 标签(非贪婪匹配)
const regStyle = /<style>[\s\S]*?<\/style>/;
const regScript = /<script>[\s\S]*?<\/script>/;

// 3. 递归创建输出目录(核心修复:避免目录不存在报错)
fs.mkdir(outputDir, { recursive: true }, (err) => {
  if (err) throw err;
  // 目录创建成功后读取 HTML 文件
  readHtmlFile();
});

// 读取 HTML 文件
function readHtmlFile() {
  fs.readFile(htmlPath, 'utf8', (err, data) => {
    if (err) {
      console.error('读取 HTML 文件失败:', err);
      return;
    }
    // 执行分离操作
    resolveCSS(data);
    resolveJS(data);
    resolveHTML(data);
  });
}

// 提取并写入 CSS
function resolveCSS(htmlStr) {
  const cssContent = regStyle.exec(htmlStr)[0]
    .replace('<style>', '')
    .replace('</style>', '');
  
  const cssPath = path.join(outputDir, 'index.css');
  fs.writeFile(cssPath, cssContent, (err) => {
    err ? console.error('CSS 写入失败') : console.log('CSS 写入成功');
  });
}

// 提取并写入 JS
function resolveJS(htmlStr) {
  const jsContent = regScript.exec(htmlStr)[0]
    .replace('<script>', '')
    .replace('</script>', '');
  
  const jsPath = path.join(outputDir, 'index.js');
  fs.writeFile(jsPath, jsContent, (err) => {
    err ? console.error('JS 写入失败') : console.log('JS 写入成功');
  });
}

// 生成新的 HTML
function resolveHTML(htmlStr) {
  const newHtml = htmlStr
    .replace(regStyle, '<link rel="stylesheet" href="./index.css">')
    .replace(regScript, '<script src="./index.js"></script>');

  const newHtmlPath = path.join(outputDir, 'index.html');
  fs.writeFile(newHtmlPath, newHtml, (err) => {
    err ? console.error('HTML 写入失败') : console.log('HTML 写入成功');
  });
}

运行方式

  1. 确保文件结构正确

  2. 终端执行命令:

node 文件名.js
  1. 执行成功后,根目录会生成 clock 文件夹,包含分离后的 3 个文件

注意事项

  1. fs.writeFile() 只能创建文件,不能自动创建目录,必须提前用 fs.mkdir 创建

  2. 重复写入同一文件,新内容会覆盖旧内容

  3. 正则表达式使用非贪婪匹配 [\s\S]*?,避免匹配多余内容

  4. 所有路径必须使用 path.join 拼接,保证跨平台兼容

补充说明

最佳实践

  1. 路径拼接优先用 path.join,需要绝对路径用 path.resolve

  2. 所有文件操作必须搭配 path 模块,杜绝硬编码路径

  3. 写入文件前,务必先判断 / 创建目标目录

  4. 路径操作必须做错误处理,避免程序崩溃

跨平台适配

path 模块会自动根据操作系统切换路径分隔符,这是 Node.js 跨平台开发的核心保障,永远不要手动写死路径分隔符

常见错误

  1. 直接用 + 拼接路径 → 跨平台报错

  2. 未创建目录直接写入文件 → 找不到路径报错

  3. Windows 系统未转义反斜杠 → 路径解析失败


总结

  1. 核心作用path 模块解决跨平台路径问题,是 fs 模块的最佳搭档

  2. 高频方法join(拼接)、resolve(绝对路径)、basename(文件名)、extname(扩展名)

  3. 核心规则:路径拼接必用 path.join,写入文件前必创建目录

  4. 实战价值:可快速实现文件拆分、路径解析、文件管理等开发需求