Node.js:path(路径)

path 模块用来处理文件和目录路径。引入方式:require('path')require('node:path'),二者等价。它做的是 字符串层面 的拼接、解析、规范化,不会访问磁盘。

默认行为跟当前操作系统走:在 Windows 上按 Windows 路径规则处理,在 POSIX 上按 POSIX 规则处理。跨平台要结果一致时,显式用 path.win32path.posix

Windows 与 POSIX 的对比

Windows 风格路径

标准 DOS 路径可由以下三部分组成:

  • 卷号或驱动器号,后跟卷分隔符(:
  • 目录名称。目录分隔符用来分隔嵌套目录
  • 可选的文件名。目录分隔符用来分开路径和文件名

三项都有,就是绝对路径。未指定卷号、且目录以分隔符开头,则相对 当前驱动器的根。否则相对当前目录。常见写法:

路径 描述
C:\Documents\Newsletters\Summer2018.pdf C: 驱动器上的绝对文件路径
\Program Files\Custom Utilities\StringFinder.exe 当前驱动器根上的绝对路径
2018\January.xlsx 当前目录的子目录中的相对路径
..\Publications\TravelBrochure.pdf 从当前目录上溯后再进入的相对路径
C:\Projects\apilibrary\apilibrary.sln C: 驱动器上的绝对路径
C:Projects\apilibrary\apilibrary.sln 相对 C: 驱动器 当前目录 的路径(冒号后没有分隔符)

Windows 上 Node 还遵循「每个驱动器各自一份当前目录」:path.resolve('C:\\')path.resolve('C:') 结果可以不同。

POSIX 是什么

POSIX(Portable Operating System Interface,可移植操作系统接口)是 IEEE(Institute of Electrical and Electronics Engineers,电气与电子工程师协会)为各种 UNIX 类系统上的应用程序定义的一套 API 标准,正式称呼是 IEEE 1003,国际标准编号 ISO/IEC 9945。制定它是为了让同一套程序更容易在不同 UNIX 之间移植。

POSIX.1 已被 ISO(International Organization for Standardization,国际标准化组织)接受,对应 ISO/IEC 9945-1:1990。

POSIX 主要由四部分组成:

  • XBD(Base Definitions volume):通用术语、概念、接口,以及 cdmkdircpmv 等工具和 stdio.hstdlib.hpthread.h 等头文件
  • XSH(System Interface volume):系统服务,例如线程、套接字、标准 IO、信号处理、错误处理
  • XCU(Shell and Utilities volume):shell 语法、关键字,以及 breakcdcpcontinuepwdreturn
  • XRAT(Rationale volume):标准相关的历史,以及采纳或舍弃某功能的理由

在 Node 的 path 文档里,POSIX 就是「非 Windows 的那套路径规则」:分隔符是 /,没有盘符。

不同的路径解析结果

path.basename() 在 POSIX 和 Windows 上结果不同。Windows 同时接受正斜杠 / 和反斜杠 \ 做目录分隔符;Unix 类系统只认 /

在 Windows 上:

const path = require('path');
path.basename('C:\\a\\b.html');       // 'b.html'
path.win32.basename('C:\\a\\b.html'); // 'b.html'

要在任意操作系统上按 Windows 规则解析 Windows 路径,用 path.win32

在 POSIX 上:

const path = require('path');
path.basename('C:\\a\\b.html');       // 'C:\\a\\b.html'
path.posix.basename('C:\\a\\b.html'); // 'C:\\a\\b.html'
path.win32.basename('C:\\a\\b.html'); // 'b.html'

要在任意操作系统上按 POSIX 规则解析 POSIX 路径,用 path.posix

path 方法

basename(path[, ext])

返回路径的最后一部分,尾部分隔符会被忽略。第二个参数是可选的扩展名;匹配时会从结果里去掉这段后缀。

path 不是字符串,或给了 ext 但不是字符串,抛 TypeError

const path = require('path');
path.basename('/demo-lizh/node/package');               // 'package'
path.basename('/demo-lizh/node/package.json');          // 'package.json'
path.basename('/demo-lizh/node/package.json', '.json'); // 'package'

Windows 通常不区分文件名大小写,但 basename 对扩展名 区分大小写

path.basename('/demo-lizh/node/package.json', '.json'); // 'package'
path.basename('/demo-lizh/node/package.json', '.JSON'); // 'package.json'

dirname(path)

返回路径的目录名,尾部分隔符会被忽略。path 不是字符串则抛 TypeError

const path = require('path');
path.dirname('/demo-lizh/node/package');      // '/demo-lizh/node'
path.dirname('/demo-lizh/node/package/');     // '/demo-lizh/node'
path.dirname('/demo-lizh/node/package.json'); // '/demo-lizh/node'

extname(path)

返回扩展名:最后一部分里 最后一个 . 起到字符串末尾。最后一部分没有 .,或除了第一个字符外没有 .(例如 .package),返回空字符串。path 不是字符串则抛 TypeError

const path = require('path');
path.extname('/demo-lizh/node/package');      // ''
path.extname('.package');                     // ''
path.extname('/demo-lizh/node/package.json'); // '.json'
path.extname('index.coffee.md');              // '.md'
path.extname('index.');                       // '.'

normalize(path)

规范化路径:解析 ...;连续多个分隔符(POSIX 上的 /,Windows 上的 \/)收成一个平台分隔符。尾部分隔符会保留。空字符串返回 '.'(当前工作目录)。不是字符串则抛 TypeError

这是字符串规范化,并不严格等同于操作系统解析路径的全部规则(例如 POSIX 上两个前导 / 有时有特殊含义,这里仍会收成一个 /)。

在 POSIX 上:

const path = require('path');
path.normalize('demo-lizh/node////////package.json'); // 'demo-lizh/node/package.json'
path.normalize('demo-lizh/node/package.json/..');     // 'demo-lizh/node'
path.normalize('');                                   // '.'

在 Windows 上:

path.normalize('C:\\temp\\\\foo\\bar\\..\\'); // 'C:\\temp\\foo\\'
path.win32.normalize('C:////temp\\\\/\\/\\/foo/bar'); // 'C:\\temp\\foo\\bar'

join([...paths])

用平台分隔符把片段接起来,再做一次 normalize。长度为 0 的片段会忽略;接完后仍是空字符串则返回 '.'。任一片段不是字符串则抛 TypeError

const path = require('path');
path.join('demo-lizh', 'node', 'package.json'); // POSIX: 'demo-lizh/node/package.json'
path.join('demo-lizh', '', 'package.json');     // 'demo-lizh/package.json'
path.join('');                                  // '.'

resolve([...paths])

把一段路径解析成 绝对路径。从右往左处理,后面的片段接到前面,直到构造出绝对路径。

  • 全部处理完仍不是绝对路径,就用当前工作目录补上
  • 结果会规范化,尾部斜杠会去掉(解析到根目录除外)
  • 零长度片段忽略
  • 一个参数都不传,返回当前工作目录的绝对路径
  • 任一参数不是字符串则抛 TypeError
const path = require('path');
path.resolve('/demo-lizh', 'node', 'package.json');  // '/demo-lizh/node/package.json'
path.resolve('demo-lizh', 'node', 'package.json');   // 相对 cwd,例如 '/Users/lizhao/Documents/.../demo-lizh/node/package.json'
path.resolve('/demo-lizh', '/node', 'package.json'); // '/node/package.json'
path.resolve('/demo-lizh/node/json/', '../package.json'); // '/demo-lizh/node/package.json'
path.resolve(''); // 当前工作目录
path.resolve();   // 当前工作目录

relative(from, to)

根据当前工作目录,给出从 fromto 的相对路径。两者经 path.resolve() 后相同,则返回空字符串。fromto 传空字符串时,用当前工作目录代替。不是字符串则抛 TypeError

在 POSIX 上:

const path = require('path');
path.relative('/demo-lizh/node/nodejs/path.js', '/demo-lizh/node/package.json'); // '../../package.json'
path.relative('node/package.json', 'node/package.json'); // ''
path.relative('node/package.json', '');                  // 相对 cwd,例如 '../..'

在 Windows 上:

path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb'); // '..\\..\\impl\\bbb'

UNC 路径在 Windows 上会保留前导斜杠。

format(pathObject)

把对象拼成路径字符串,是 path.parse() 的逆操作。对象字段:

{
  dir: '',
  root: '',
  base: '',
  name: '',
  ext: ''
}

优先级:

  • 提供了 dir,则忽略 root
  • 提供了 base,则忽略 extname
const path = require('path');

path.format({
  root: '/Documents/',
  name: 'package-lock',
  ext: '.json'
});
// '/Documents/package-lock.json'

path.format({
  dir: '/lizhao/demo-lizh/node',
  base: 'package.json',
  root: '/Documents',
  name: 'package-lock',
  ext: '.json'
});
// '/lizhao/demo-lizh/node/package.json'

只有 root、没有 dir 时,root 按根路径来写(POSIX 上常带末尾 /);有 dir 时不必再写 root。Node 19 起,ext 没写点号也会自动补上:ext: 'json'ext: '.json' 效果相同。

parse(path)

把路径拆成对象,尾部分隔符忽略。path 不是字符串则抛 TypeError。字段是 rootdirbaseextname

在 POSIX 上:

const path = require('path');
console.log(path.parse('/demo-lizh/node/package.json'));
// {
//   root: '/',
//   dir: '/demo-lizh/node',
//   base: 'package.json',
//   ext: '.json',
//   name: 'package'
// }

console.log(path.parse('demo-lizh/node/package.json'));
// { root: '', dir: 'demo-lizh/node', base: 'package.json', ext: '.json', name: 'package' }

console.log(path.parse(''));
// { root: '', dir: '', base: '', ext: '', name: '' }

绝对路径的 dir 包含 root/C:\\),相对路径的 root 是空字符串。

在 Windows 上:

const path = require('path');
path.parse('C:\\demo-lizh\\node\\package.json');
// {
//   root: 'C:\\',
//   dir: 'C:\\demo-lizh\\node',
//   base: 'package.json',
//   ext: '.json',
//   name: 'package'
// }

path.parse('demo-lizh\\node\\package.json');
// { root: '', dir: 'demo-lizh\\node', base: 'package.json', ext: '.json', name: 'package' }

path.parse('');
// { root: '', dir: '', base: '', ext: '', name: '' }

isAbsolute(path)

判断 字面量 路径是不是绝对路径。空字符串返回 false。不是字符串则抛 TypeError。它不做磁盘解析,也 不能 用来防路径穿越。

在 POSIX 上:

const path = require('path');
path.isAbsolute('/demo-lizh/node/package.json'); // true
path.isAbsolute('./package.json');               // false
path.isAbsolute('');                             // false

在 Windows 上:

path.isAbsolute('//server');    // true
path.isAbsolute('\\\\server');  // true
path.isAbsolute('C:/foo/..');   // true
path.isAbsolute('C:\\foo\\..'); // true
path.isAbsolute('bar\\baz');    // false
path.isAbsolute('bar/baz');     // false
path.isAbsolute('.');           // false

toNamespacedPath(path)

仅 Windows 有意义:返回带命名空间前缀的等价路径(例如 \\?\ 或 UNC 的 \\?\UNC\),以便绕过旧版 MAX_PATH 限制。path 不是字符串则原样返回。POSIX 上这是空操作,始终返回入参。

matchesGlob(path, pattern)

判断 path 是否匹配 glob 模式。pathpattern 不是字符串则抛 TypeError。Node 22.5、20.17 起提供,后续版本已标为稳定。

path.matchesGlob('/foo/bar', '/foo/*'); // true
path.matchesGlob('/foo/bar*', 'foo/bird'); // false

path 属性

posix

POSIX 实现。也可用 require('path/posix')require('node:path/posix') 直接拿到。

path.posix.basename('/demo-lizh/node/package');
path.posix.join('demo-lizh', 'node', 'package.json');

win32

Windows 实现。也可用 require('path/win32')require('node:path/win32')

path.win32.basename('/demo-lizh/node/package');
path.win32.join('demo-lizh', 'node', 'package.json');

Windows 上 path 方法写入路径时只用 \,但解析时 /\ 都认。

delimiter

平台路径 列表 定界符:Windows 是 ;,POSIX 是 :。用来拆 PATH 这类环境变量,不是文件路径里的 /\

在 POSIX 上:

const path = require('path');
process.env.PATH;                       // /usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin
process.env.PATH.split(path.delimiter); // ['/usr/local/bin', '/usr/local/sbin', '/usr/bin', '/bin', '/usr/sbin', '/sbin']

在 Windows 上:

process.env.PATH;                        // C:\Windows\system32;C:\Windows;C:\Program Files\node\
process.env.PATH.split(path.delimiter); // ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']

sep

平台路径 片段 分隔符:Windows 是 \,POSIX 是 /

在 POSIX 上:

path.sep; // '/'
'foo/bar/baz'.split(path.sep); // ['foo', 'bar', 'baz']

在 Windows 上:

path.sep; // '\\'
'foo\\bar\\baz'.split(path.sep); // ['foo', 'bar', 'baz']

参考资料

Path | Node.js

Windows 系统中的文件路径格式

POSIX 简介(补充阅读)

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-09-02 01:42:11

results matching ""

    No results matching ""