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()
相反。将pathObject
的root
、dir
、base
、name
、ext
属性,按照一定的规则,组合成一个文件路径
当 pathObject
提供的属性有组合时,有些属性的优先级比其他的高:
- 如果提供了
pathObject.dir
,则pathObject.root
会被忽略 - 如果提供了
pathObject.base
存在,则pathObject.ext
和pathObject.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()
方法返回从from
到to
的相对路径(基于当前工作目录)。 如果from
和to
各自解析到同一路径(调用path.resolve()
),则返回一个长度为零的字符串。如果from
或to
传入了一个长度为零的字符串,则当前工作目录会被用于代替长度为零的字符串。
在 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\\']