Node.js path(路径) 模块与几种文件路径学习笔记

2935 5 年前
Node.js path 模块提供了一些用于处理文件路径的小工具,在nodejs中,path是个使用频率很高,但却让人又爱又恨的模块。部分因为文档说的不够清晰,部分因为接口的平台差异性。

Node.js中的文件路径大概有 __dirname, __filename, process.cwd(), ./ 或者 ../,前三个都是绝对路径,为了便于比较,./../ 我们通过 path.resolve('./')来转换为绝对路径。

__dirname:    获得当前执行文件所在目录的完整目录名
__filename:   获得当前执行文件的带有完整绝对路径的文件名
process.cwd():获得当前执行node命令时候的文件夹目录名
./:           文件所在目录(执行nnode命令)

假如,我有一个文件的目录结构如下:

editor/
  - dist/
  - src/
      - task.js

然后我们在task.js文件中写入一下代码

const path = require('path');
console.log(__dirname);
console.log(__filename);
console.log(process.cwd());
console.log(path.resolve('./'));

在editor目录下运行node src/task.js,我们可以看到结果如下:

/Users/laihuamin/Documents/richEditor/editor/src
/Users/laihuamin/Documents/richEditor/editor/src/task.js
/Users/laihuamin/Documents/richEditor/editor
/Users/laihuamin/Documents/richEditor/editor

然后我们有可以在src目录下运行这个文件,node task.js,运行结果如下:

/Users/laihuamin/Documents/richEditor/editor/src
/Users/laihuamin/Documents/richEditor/editor/src/task.js
/Users/laihuamin/Documents/richEditor/editor/src
/Users/laihuamin/Documents/richEditor/editor/src

对比两个输出结果,我们可以归纳一下几点:

  • __dirname:获得当前执行文件所在目录的完整目录名
  • __filename:获得当前执行文件的带有完整绝对路径的文件名
  • process.cwd():你运行node命令所在文件夹的位置,比如你在src目录下运行,那么就是输出到src为止。
  • ./:同process.cwd()

Node.js path 模块提供了一些用于处理文件路径的小工具,在nodejs中,path是个使用频率很高,但却让人又爱又恨的模块。部分因为文档说的不够清晰,部分因为接口的平台差异性

引入 path 模块

const path = require('path');

Path 模块 的方法

path.basename(path[, ext])

path.basename() 方法返回一个参数 path 的最后一部分,类似于 Unix 中的 basename 命令,没有尾部文件分隔符(Windows:\,POSIX:/)

  • path:路径
  • ext:可选的文件扩展名
path.basename('/foo/bar/baz/asdf/quux.html');
// 返回: 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html', '.html');
// 返回: 'quux'

注意path.basename(path) 只是输出路径的最后一部分且不包含尾部文件分隔符(\或/),并不会判断到底是文件名还是只有路径

var path = require('path');

// 输出:test.js
console.log( path.basename('/tmp/demo/js/test.js') );

// 输出:test
console.log( path.basename('/tmp/demo/js/test/') );

// 输出:test
console.log( path.basename('/tmp/demo/js/test') );

path.dirname(path)

path.dirname() 方法返回一个 path 的目录名,类似于 Unix 中的 dirname 命令。

path.dirname('/foo/bar/baz/asdf/quux');
// 返回: '/foo/bar/baz/asdf'
var filepath = '/tmp/demo/js/test.js';
// 输出:/tmp/demo/js
console.log( path.dirname(filepath) );
var filepath = '/tmp/demo/js/test/';
// 输出:/tmp/demo/js
console.log( path.dirname(filepath) );

由上面的例子可以看出,path.dirname()如果尾部是文件分隔符,则忽略尾部是文件分隔符,认为参数倒数第二个文件分隔符后字符串为文件名。规则同path.basename()

path.extname(path)

path.extname() 方法返回 path 的扩展名,即从 path 的最后一部分中的最后一个 .(句号)字符到字符串结束。 如果 path 的最后一部分没有 .path 的文件名的第一个字符是 .,则返回一个空字符串。

var filepath = '/tmp/demo/js/test/main.js';
path.extname(filepath);
// 返回: '.js'

path.extname('index.html');
// 返回: '.html'

path.extname('index.coffee.md');
// 返回: '.md'

path.extname('index.');
// 返回: '.'

path.extname('index');
// 返回: ''

path.extname('.index');
// 返回: ''

path.format(pathObject)

path.format() 方法会从一个对象返回一个路径字符串。 与 path.parse() 相反。将pathObjectrootdirbasenameext属性,按照一定的规则,组合成一个文件路径

pathObject 提供的属性有组合时,有些属性的优先级比其他的高:

  • 如果提供了 pathObject.dir,则 pathObject.root 会被忽略
  • 如果提供了 pathObject.base 存在,则 pathObject.extpathObject.name 会被忽略

Posix例子:

// If `dir` and `base` are provided, `dir` + platform separator + `base`
// will be returned.
path.format({
    dir: '/home/user/dir',
    base: 'file.txt'
});
// returns '/home/user/dir/file.txt'

// `root` will be used if `dir` is not specified.
// `name` + `ext` will be used if `base` is not specified.
// If only `root` is provided or `dir` is equal to `root` then the
// platform separator will not be included.
path.format({
    root: '/',
    base: 'file.txt'
});
// returns '/file.txt'

path.format({
    dir: '/',
    root: '/',
    name: 'file',
    ext: '.txt'
});
// returns '/file.txt'

// `base` will be returned if `dir` or `root` are not provided.
path.format({
    base: 'file.txt'
});
// returns 'file.txt'

Windows例子

path.format({
    root : "C:\\",
    dir : "C:\\path\\dir",
    base : "file.txt",
    ext : ".txt",
    name : "file"
})

path.isAbsolute(path)

path.isAbsolute() 方法会判定 path 是否为一个绝对路径。如果给定的 path 是一个长度为零的字符串,则返回 false

POSIX 上:

path.isAbsolute('/foo/bar'); // true
path.isAbsolute('/baz/..');  // true
path.isAbsolute('qux/');     // 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

path.join([...paths])

path.join() 方法使用平台特定的分隔符(Unix系统是"/",Windows系统是"\")把全部给定的 path 片段连接到一起,并规范化生成的路径。长度为零的 path 片段会被忽略。 如果连接后的路径字符串是一个长度为零的字符串,则返回 '.',表示当前工作目录。 如果任一 path 路径片段不是一个字符串,则会报错。

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'

path.join('foo', {}, 'bar');
// 抛出 'TypeError: Path must be a string. Received {}'

path.normalize(path)

path.normalize() 方法会规范化给定的 path,并解析 '..' 和 '.' 片段。当发现多个连续的路径分隔符时(如 POSIX 上的 / 与 Windows 上的 \/),它们会被单个的路径分隔符替换。 末尾的多个分隔符会被保留。 如果 path 是一个长度为零的字符串,则返回 '.',表示当前工作目录。

POSIX 上:

path.normalize('/foo/bar//baz/asdf/quux/..');
// 返回: '/foo/bar/baz/asdf'

Windows 上:

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

尽管Windows会识别多种文件路径分隔符,但是两种分隔符在Window上会被(\)分隔符取代:

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

如果 path 不是一个字符串,则报错。

请查看下列各种情况的输出说明:

var path = require('path');
var filepath = '/tmp/demo/js/test.js';

var index = 0;

var compare = function(desc, callback){
  console.log('[用例%d]:%s', ++index, desc);
  callback();
  console.log('\n');
};

compare('路径为空', function(){
  // 输出 .
  console.log( path.normalize('') );
});

compare('路径结尾是否带/', function(){
  // 输出 /tmp/demo/js/upload
  console.log( path.normalize('/tmp/demo/js/upload') );

  // /tmp/demo/js/upload/
  console.log( path.normalize('/tmp/demo/js/upload/') );
});

compare('重复的/', function(){
  // 输出 /tmp/demo/js
  console.log( path.normalize('/tmp/demo//js') );
});

compare('路径带..', function(){
  // 输出 /tmp/demo/js
  console.log( path.normalize('/tmp/demo/js/upload/..') );
});

compare('相对路径', function(){
  // 输出 demo/js/upload/
  console.log( path.normalize('./demo/js/upload/') );

  // 输出 demo/js/upload/
  console.log( path.normalize('demo/js/upload/') );
});

compare('不常用边界', function(){
  // 输出 ..
  console.log( path.normalize('./..') );

  // 输出 ..
  console.log( path.normalize('..') );

  // 输出 ../
  console.log( path.normalize('../') );

  // 输出 /
  console.log( path.normalize('/../') );
  
  // 输出 /
  console.log( path.normalize('/..') );
});

path.parse(path)

path.parse() 方法返回一个对象,对象的属性表示 path 的元素。 尾部文件分隔符会被忽略

返回的对象有以下属性:

dir <string>
root <string>
base <string>
name <string>
ext <string>

POSIX 上:

path.parse('/home/user/dir/file.txt');
// 返回:
// { root: '/',
//   dir: '/home/user/dir',
//   base: 'file.txt',
//   ext: '.txt',
//   name: 'file'
// }
┌─────────────────────┬────────────┐
│          dir        │    base    │
├──────┬              ├──────┬─────┤
│ root │              │ name │ ext │
"  /    home/user/dir / file  .txt "
└──────┴──────────────┴──────┴─────┘
(请无视以上字符串中的空格,它们只是为了布局)

Windows 上:

path.parse('C:\\path\\dir\\file.txt');
// 返回:
// { root: 'C:\\',
//   dir: 'C:\\path\\dir',
//   base: 'file.txt',
//   ext: '.txt',
//   name: 'file'
// }
┌─────────────────────┬────────────┐
│          dir        │    base    │
├──────┬              ├──────┬─────┤
│ root │              │ name │ ext │
" C:\      path\dir   \ file  .txt "
└──────┴──────────────┴──────┴─────┘
(请无视以上字符串中的空格,它们只是为了布局)
var myFilePath = '/someDir/someFile.json';
path.parse(myFilePath).base
// "someFile.json"
path.parse(myFilePath).name
// "someFile"
path.parse(myFilePath).ext
// ".json"

path.relative(from, to)

path.relative() 方法返回从 fromto 的相对路径(基于当前工作目录)。 如果 fromto 各自解析到同一路径(调用 path.resolve()),则返回一个长度为零的字符串。如果 fromto 传入了一个长度为零的字符串,则当前工作目录会被用于代替长度为零的字符串。

POSIX 上:

path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
// 返回: '../../impl/bbb'

Windows 上:

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

path.resolve([...paths])

path.resolve() 方法会把一个路径或路径片段的序列解析为一个绝对路径。 如果处理完全部给定的 path 片段后还未生成一个绝对路径,则当前工作目录会被用上。 生成的路径是规范化后的,且末尾的斜杠会被删除,除非路径被解析为根目录。 长度为零的 path 片段会被忽略。 如果没有传入 path 片段,则 path.resolve() 会返回当前工作目录的绝对路径。

var path = require('path');

// 假设当前工作路径是 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path
console.log( path.resolve('') )

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path
console.log( path.resolve('.') )

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz') );

// 输出 /foo/bar/baz
console.log( path.resolve('/foo/bar', './baz/') );

// 输出 /tmp/file
console.log( path.resolve('/foo/bar', '/tmp/file/') );

// 输出 /Users/a/Documents/git-code/nodejs-learning-guide/examples/2016.11.08-node-path/www/js/mod.js
console.log( path.resolve('www', 'js/upload', '../mod.js') );

path.toNamespacedPath(path)

Path 模块 的属性

path.posix

path.posix 属性提供了 path 方法针对 POSIX 的实现

path.win32

path.win32 属性提供了 path 方法针对 Windows 的实现。

path.sep

平台的路径片段分隔符:

  • Windows 上是 \
  • POSIX 上是 /

POSIX 上:

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

Windows 上:

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

注意:在 Windows 上,斜杠字符(/)和反斜杠字符(\)都可作为路径分隔符; 但 path 的方法只添加反斜杠(\)。

path.delimiter

平台的路径分隔符

  • Windows 上是 ;
  • POSIX 上是 :

例如在 POSIX 上:

console.log(process.env.PATH);
// 输出: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'
process.env.PATH.split(path.delimiter);
// 返回: ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']

Windows 上:

console.log(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\\']
没有了
分类栏目
© 2018邮箱:11407215#qq.comGitHub沪ICP备12039518号-6