20-本地路径处理-path

288 阅读6分钟

本地路径处理-path

// 在nodejs当中,path是个使用频率很高,但是却让人又爱又恨的模块,部分因为文档说的不够清楚,部分因为接口的平台差异性

获取路径/文件名/扩展名

// 获取路径: path.dirname(filepath);
// 获取文件名: path.basename(filepath);
// 获取扩展名: path.extname(filepath);

获取所在路径

console.log(path.dirname(filepath)); // /practice/path

获取文件名

// 从严格意义上来说, path.dirname(filepath);只是输出路径的最后一部分,并不会判断是否文件名,但是大部分的时候,我们可以用它来作为简易的获取文件名的方法
console.log(path.basename(filepath)); // index.js
console.log(path.basename("/practice/path/")); // path
console.log(path.basename("/practice/path")); // path

// 可见只是输出了后面一部分,如果指向获取文件名,单不包括文件扩展呢,可以用上第二个参数
console.log(path.basename(filepath, ".js")); // index

获取文件扩展名

console.log(path.extname(filepath)); // .js
// 更加细节的规则是如下, 假设 path.basename(filepath) === B
// 从B的最后一个'.'开始截取,直到最后一个字符
// 如果B中不能存在'.',或者B的第一个字符就是'.' 那么就返回空字符串
console.log(path.extname("index.js")); // .js
console.log(path.extname("index.coffee.js")); // .js
console.log(path.extname("index.")); // .
console.log(path.extname("index")); //
console.log(path.extname(".index")); // .

路径组合

// path.join([...paths]);
// path.resolve([...paths]);

path.join([...paths])

// 把paths拼起来,然后再normalize一下,这句话反正我自己看着也很莫名其妙,可以参考下面的伪代码定义
console.log(path.join(...[".foo", "bar", "bat/asd", "ad", ".."])); //.foo\bar\bat\asd

// path定义的的伪代码如下
module.exports.join = function () {
  const paths = Array.prototype.slice.call(arguments, 0);
  return this.normalize(path.join("/"));
};

path.resolve([...paths])

// 这个接口的说明有点啰嗦,你可以想象现在你在shell下面,从左到右运行一遍 cd path 命令,最终获取的绝对路径/文件名,就是这个接口所返回的结果了.

// 比如 path.resolve('/foo/bar','./baz')  可以看成下面命令的集合
// cd /foo/bar
// cd ./baz
console.log(path.resolve("")); // D:\Node-learning\nodejs-learning-guide-master\practice\path
console.log(path.resolve(".")); // D:\Node-learning\nodejs-learning-guide-master\practice\path
console.log(path.resolve("/foo/bar", "./baz")); // D:\foo\bar\baz
console.log(path.resolve("/foo/bar", "./baz/")); // D:\foo\bar\baz
console.log(path.resolve("./foo/bar", "/tmp/file/")); // D:\tmp\file
console.log(path.resolve("www", "js/upload", "../mod.js")); // D:\Node-learning\nodejs-learning-guide-master\practice\path\www\js\mod.js

路径解析

path.normalize(filepath)

// 从官方文档的描述来看,path.normalize(filepath)应该是一个比较简答的API
// API的说明:
// 1.如果路径为空,返回 . 相当于当前的工作路径
// 2. 将对路径中的重复的路径分隔符,比如Linux下的/合并为一个
// 3. 对路径中的. .. 进程处理,(类似shell里的 cd..)
// 4. 如果路径最后有/,那么保留/

let index = 0;
const compare = function (desc, callback) {
  console.log("[用例%d]:%s", ++index, desc);
  callback();
  console.log("\n");
};
compare("路径为空", function () {
  console.log(path.resolve(""));
  // [用例1]:路径为空
  // D:\Node-learning\nodejs-learning-guide-master\practice\path
});
compare("路径结尾是否带/", function () {
  // [用例2]:路径结尾是否带/
  // \aa\cc\cc\dd
  // \aa\cc\cc\dd\
  console.log(path.normalize("/aa/cc/cc/dd"));
  console.log(path.normalize("/aa/cc/cc/dd/"));
});
compare("重复的/", function () {
  // [用例3]:重复的/
  // \aa\bb\cc
  console.log(path.normalize("/aa/bb//cc"));
});
compare("路径带..", function () {
  // [用例4]:路径带..
  // aa\bb
  console.log(path.normalize("aa/bb/cc/.."));
});
compare("相对路径", () => {
  // [用例5]:相对路径
  // aa\bb\cc\
  // aa\bb\cc\
  console.log(path.normalize("./aa/bb/cc/"));
  console.log(path.normalize("aa/bb/cc/"));
});
compare("不常用边界", function () {
  // [用例6]:不常用边界
  // ..
  // ..
  // ..\
  // \
  // \
  console.log(path.normalize("./.."));
  console.log(path.normalize(".."));
  console.log(path.normalize("../"));
  console.log(path.normalize("/../"));
  console.log(path.normalize("/.."));
});
// 可以看下 path.normalize(filepath) 的node源码 https://github.com/nodejs/node/blob/master/lib/path.js

文件路径分解/组合

// path.format(pathObject) 将 pathObject的 root,dir,base,name,ext属性,按照一定的规则,组合成一个文件地址
// path.parse(filepath): path.format() 方法的反向操作
// 我们先来看看官网对相关属性的说明。

首先是linux下
┌─────────────────────┬────────────┐
│          dir        │    base    │
├──────┬              ├──────┬─────┤
│ root │              │ name │ ext │
"  /    home/user/dir / file  .txt "
└──────┴──────────────┴──────┴─────┘
(all spaces in the "" line should be ignored -- they are purely for formatting)

然后是windows下
┌─────────────────────┬────────────┐
│          dir        │    base    │
├──────┬              ├──────┬─────┤
│ root │              │ name │ ext │
" C:\      path\dir   \ file  .txt "
└──────┴──────────────┴──────┴─────┘
// (all spaces in the "" line should be ignored -- they are purely for formatting)

path.format(pathObject)

// path.format(pathObject)中,pathObject的配置属性可以进一步精简,根据接口描述来看,一下两者是等价的
// root vs dir 两者是可以互相替换的,区别在于,路径拼接的时候,root后面不会自动加/,而dir会
// base vs name+ext 两者可以互相替换
const p1 = path.format({
  root: "/aa/",
  base: "hello.js",
});
console.log(p1); // /aa/hello.js
const p2 = path.format({
  dir: "/aa",
  name: "hello",
  ext: ".js",
});
console.log(p2); ///aa\hello.js

path.parse(filepath)

// path.parse是 path.format(pathObject)的反响操作
// 四个属性,对于使用者还是挺方便的,不过 path.format(pathObject) 中也有四个配置属性,容易搞混
console.log(path.parse("/aa/bb/cc.txt"));
// {
//   root: '/',
//   dir: '/aa/bb',
//   base: 'cc.txt',
//   ext: '.txt',
//   name: 'cc'
// }

获取相对路径

// path.relative(from, to);
// 描述: 从 from 路径到 to 路径的相对路径
// 边界:
// 如果 from to 指向同个路径,那么返回空字符串
// 如果 from to 中任意一个为空,那么返回当前工作路径

const p1 = path.relative("/aa/bb/cc/dd", "aa/bb/ee/ff");
console.log(p1); // ..\..\..\..\Node-learning\nodejs-learning-guide-master\practice\path\aa\bb\ee\ff
const p2 = path.relative("aa/bb", "aa/bb");
console.log(p2); //
const p3 = path.relative("/aa/bb", "");
console.log(p3); // ..\..\Node-learning\nodejs-learning-guide-master\practice\path

平台相关接口/属性

// 以下接口属性都跟平台的具体实现相关,也就是说,同样的属性接口在不同的平台上表现不同
// path.posix path相关属性,接口的Linux实现
// path.win32 path相关属性,接口win32实现
// path.sep 路劲分隔符,在linux上是/,在window上是\
// path.delimiter path设置的分隔符,linux上是: window上是;
// 注意:当使用path.win32 相关接口时,参数同样可以使用/做分隔符,但接口返回值分隔符只会是\

console.log(path.win32.join("/tmp", "fuck")); // \tmp\fuck
console.log(path.win32.sep); // \
console.log(path.win32.join("aa", "bb")); // aa\bb
console.log(path.win32.join("/aa", "bb")); // \aa\bb

path.delimiter

// window例子
console.log(process.env.PATH);
// C:\Program Files\VanDyke Software\Clients\;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\QuickTime\QTSystem\;C:\Program Files\TortoiseSVN\bin;C:\Program Files\Git\cmd;D:\nvm;D:\nodejs;D:\software\NodeTools\;D:\software\NodeTools\\nodejs;D:\software\NodeTools\\node_npm;D:\software\NodeTools\\HttpServer\install;D:\software\NodeTools\\HttpServer\;D:\Develop\nodejs\;D:\Develop\nodejs\node_global;C:\Users\259776\AppData\Roaming\npm;D:\nvm;D:\nodejs

console.log(process.env.PATH.split(path.delimiter));
// [
//   'C:\\Program Files\\VanDyke Software\\Clients\\',
//   'C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath',
//   'C:\\Windows\\system32',
//   'C:\\Windows',
//   'C:\\Windows\\System32\\Wbem',
//   'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\',
//   'C:\\Windows\\System32\\OpenSSH\\',
//   'C:\\Program Files (x86)\\QuickTime\\QTSystem\\',
//   'C:\\Program Files\\TortoiseSVN\\bin',
//   'C:\\Program Files\\Git\\cmd',
//   'D:\\nvm',
//   'D:\\nodejs',
//   'D:\\software\\NodeTools\\',
//   'D:\\software\\NodeTools\\\\nodejs',
//   'D:\\software\\NodeTools\\\\node_npm',
//   'D:\\software\\NodeTools\\\\HttpServer\\install',
//   'D:\\software\\NodeTools\\\\HttpServer\\',
//   'D:\\Develop\\nodejs\\',
//   'D:\\Develop\\nodejs\\node_global',
//   'C:\\Users\\259776\\AppData\\Roaming\\npm',
//   'D:\\nvm',
//   'D:\\nodejs'
// ]

// linux例子
console.log(process.env.PATH);
// C:\Users\259776\bin;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\local\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Users\259776\bin;C:\Program Files\VanDyke Software\Clients;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Windows\System32\OpenSSH;C:\Program Files (x86)\QuickTime\QTSystem;C:\Program Files\TortoiseSVN\bin;C:\Program Files\Git\cmd;D:\nvm;D:\nodejs;D:\software\NodeTools;D:\software\NodeTools\nodejs;D:\software\NodeTools\node_npm;D:\software\NodeTools\HttpServer\install;D:\software\NodeTools\HttpServer;D:\Develop\nodejs;D:\Develop\nodejs\node_global;C:\Users\259776\AppData\Roaming\npm;D:\nvm;D:\nodejs;C:\Program Files\Git\usr\bin\vendor_perl;C:\Program Files\Git\usr\bin\core_perl

console.log(process.env.PATH.split(path.delimiter));
// [
//   'C:\\Users\\259776\\bin',
//   'C:\\Program Files\\Git\\mingw64\\bin',
//   'C:\\Program Files\\Git\\usr\\local\\bin',
//   'C:\\Program Files\\Git\\usr\\bin',
//   'C:\\Program Files\\Git\\usr\\bin',
//   'C:\\Program Files\\Git\\mingw64\\bin',
//   'C:\\Program Files\\Git\\usr\\bin',
//   'C:\\Users\\259776\\bin',
//   'C:\\Program Files\\VanDyke Software\\Clients',
//   'C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath',
//   'C:\\Windows\\system32',
//   'C:\\Windows',
//   'C:\\Windows\\System32\\Wbem',
//   'C:\\Windows\\System32\\WindowsPowerShell\\v1.0',
//   'C:\\Windows\\System32\\OpenSSH',
//   'C:\\Program Files (x86)\\QuickTime\\QTSystem',
//   'C:\\Program Files\\TortoiseSVN\\bin',
//   'C:\\Program Files\\Git\\cmd',
//   'D:\\nvm',
//   'D:\\nodejs',
//   'D:\\software\\NodeTools',
//   'D:\\software\\NodeTools\\nodejs',
//   'D:\\software\\NodeTools\\node_npm',
//   'D:\\software\\NodeTools\\HttpServer\\install',
//   'D:\\software\\NodeTools\\HttpServer',
//   'D:\\Develop\\nodejs',
//   'D:\\Develop\\nodejs\\node_global',
//   'C:\\Users\\259776\\AppData\\Roaming\\npm',
//   'D:\\nvm',
//   'D:\\nodejs',
//   'C:\\Program Files\\Git\\usr\\bin\\vendor_perl',
//   'C:\\Program Files\\Git\\usr\\bin\\core_perl'
// ]

相关链接

// 官方文档:https://nodejs.org/api/path.html#path_path