Node.js 核心模块:path 路径模块

path 模块提供了一些实用函数,用于处理文件和目录的路径。由于不同操作系统(Windows、Linux、macOS)的路径分隔符不同,path 模块能够帮助我们以跨平台的方式安全地操作路径。本章将详细介绍 path 模块的常用方法和最佳实践。

1. 引入 path 模块

path 是 Node.js 的核心模块,无需安装,直接引入即可使用:

const path = require('path');

2. 路径基础:分隔符与路径对象

不同平台使用的路径分隔符不同:

  • Windows 使用反斜杠 \ 作为路径分隔符,但也接受正斜杠 /
  • Linux 和 macOS 使用正斜杠 /

path 模块提供了两个属性:

  • path.sep:当前平台的文件路径分隔符(Windows 上为 \,POSIX 上为 /)。
  • path.delimiter:当前平台的环境变量路径分隔符(Windows 上为 ;,POSIX 上为 :)。
console.log('路径分隔符:', path.sep);
console.log('环境变量分隔符:', path.delimiter);

3. 路径拼接:path.join()

path.join() 将多个路径片段拼接成一个完整的路径,它会根据当前平台自动添加正确的分隔符,并规范化生成的路径。

const fullPath = path.join('/users', 'node', 'app.js');
console.log(fullPath);
// POSIX 输出: /users/node/app.js
// Windows 输出: \users\node\app.js

path.join() 还会处理多余的斜杠和 ... 等:

console.log(path.join('/users', 'node', '..', 'app.js'));
// POSIX 输出: /users/app.js

4. 路径解析:path.resolve()

path.resolve() 将一系列路径或路径片段解析为绝对路径。它的处理逻辑是:从右向左组合路径,直到构造出一个绝对路径。如果组合后仍不是绝对路径,则加上当前工作目录。

console.log(path.resolve('app.js'));
// 输出当前工作目录 + app.js,例如 /home/user/project/app.js

console.log(path.resolve('/users', 'node', 'app.js'));
// 输出 /users/node/app.js

console.log(path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif'));
// 如果当前工作目录是 /home/user/project,则输出 /home/user/project/wwwroot/static_files/gif/image.gif
注意: path.resolve() 不会检查路径是否存在,它只是进行字符串运算。

5. 获取路径信息

5.1 path.basename()

返回路径的最后一部分(文件名),可选地去除扩展名。

const filePath = '/users/node/app.js';
console.log(path.basename(filePath));      // 'app.js'
console.log(path.basename(filePath, '.js')); // 'app'

5.2 path.dirname()

返回路径的目录部分。

console.log(path.dirname('/users/node/app.js')); // '/users/node'

5.3 path.extname()

返回路径中文件的扩展名(包含点)。如果没有扩展名则返回空字符串。

console.log(path.extname('index.html'));   // '.html'
console.log(path.extname('app.js'));        // '.js'
console.log(path.extname('README.md'));     // '.md'
console.log(path.extname('file.'));          // '.'
console.log(path.extname('file'));           // ''

6. 路径解析为对象:path.parse() 与 path.format()

path.parse() 将路径字符串解析为一个包含以下属性的对象:

  • root:根目录(如 /C:\
  • dir:目录路径
  • base:文件名(包含扩展名)
  • name:文件名(不含扩展名)
  • ext:扩展名(包含点)
const parsed = path.parse('/users/node/app.js');
console.log(parsed);
/* 输出(POSIX):
{
  root: '/',
  dir: '/users/node',
  base: 'app.js',
  name: 'app',
  ext: '.js'
}
*/

path.format()parse 相反,从一个对象生成路径字符串。

const obj = {
  dir: '/users/node',
  name: 'app',
  ext: '.js'
};
console.log(path.format(obj)); // '/users/node/app.js'

7. 规范化路径:path.normalize()

path.normalize() 规范化给定的路径,解析 ... 片段,并去除多余的斜杠。

console.log(path.normalize('/users//node/../app.js'));
// '/users/app.js'

8. 计算相对路径:path.relative()

path.relative() 返回从第一个路径到第二个路径的相对路径。如果两个路径相同,返回空字符串。

const from = '/users/node/app.js';
const to = '/users/node/README.md';
console.log(path.relative(from, to)); // '../README.md'

9. 跨平台路径处理:path.posix 与 path.win32

path 模块默认根据当前操作系统提供对应的方法。但你可以显式使用 path.posixpath.win32 来强制使用特定平台的实现。例如,即使你在 Windows 上,也可以处理 POSIX 风格的路径:

const posixPath = path.posix.join('users', 'node', 'app.js');
console.log(posixPath); // 'users/node/app.js'

const winPath = path.win32.join('users', 'node', 'app.js');
console.log(winPath); // 'users\\node\\app.js'

10. 常用场景示例

10.1 安全地构建文件路径

const path = require('path');

const dir = 'uploads';
const filename = 'profile.jpg';
const filePath = path.join(__dirname, dir, filename);
console.log(filePath); // 绝对路径,跨平台安全

10.2 提取文件扩展名并判断类型

function isImage(file) {
  const ext = path.extname(file).toLowerCase();
  return ['.jpg', '.jpeg', '.png', '.gif', '.bmp'].includes(ext);
}

console.log(isImage('photo.JPG')); // true

10.3 获取文件名并去除扩展名

const filename = path.basename('/path/to/file.txt', '.txt');
console.log(filename); // 'file'

11. path 模块与 __dirname、__filename

在 Node.js 模块中,__dirname__filename 分别表示当前模块的目录绝对路径和文件绝对路径。它们与 path 模块结合使用非常方便:

const path = require('path');

console.log(__dirname);               // 当前文件所在目录
console.log(__filename);              // 当前文件绝对路径
console.log(path.basename(__filename)); // 当前文件名

// 构建相对于当前文件的路径
const configPath = path.join(__dirname, 'config', 'settings.json');

12. 注意事项

  • path 模块只处理路径字符串,不检查路径是否存在或指向有效文件。
  • 在 Windows 上,path.resolve() 可能会返回以驱动器号开头的路径,例如 C:\project\file.js
  • 当使用 path.join()path.resolve() 时,如果参数中包含绝对路径,前面的参数会被忽略(取决于具体方法)。
安全提示: 当处理用户输入的路径时,务必使用 path.resolve() 并结合检查,防止目录遍历攻击(如包含 ../ 的恶意路径)。例如,可以使用 path.resolve(baseDir, userInput) 后检查结果是否以 baseDir 开头。

小结

path 模块是 Node.js 中处理文件系统路径的必备工具。通过本章的学习,你应该掌握了路径拼接、解析、格式化、规范化等核心方法,以及如何利用这些方法编写跨平台的安全代码。在后续章节中,我们将结合 fspath 模块进行更复杂的文件操作。