如何从绝对路径与指定基础路径获取相对文件名?
有没有原生函数能实现这个需求?
好问题!先分环境给你说清楚:
如果是Node.js环境,其实有个原生的
path.relative(from, to)方法正好干这个事!不过要注意参数顺序:它的第一个参数是基础路径,第二个是绝对路径,和你示例里的foo参数顺序反过来。比如你的第一个例子:const path = require('path'); path.relative('/a/d/e', '/a/b/c/1.txt'); // 返回 '../../b/c/1.txt',和你的示例结果一致而且它会自动处理路径里的
..,比如你第二个例子里的/a/b/../d/1.txt,它会先把路径规范化成/a/d/1.txt,然后计算相对路径:path.relative('/a/d/e', '/a/b/../d/1.txt'); // 返回 '../1.txt'这里和你示例里的
../c/1.txt有点出入,大概率是你示例里的绝对路径写错啦,应该是/a/b/../c/1.txt才会得到../c/1.txt~如果是浏览器环境,那就没有原生API了,得自己实现。你的思路完全没问题——先规范化路径,再找公共部分,最后拼接
..和剩余路径。其实这个实现并没有你想的那么繁琐,我给你拆解成几步:
第一步:实现路径规范化函数(替代realpath,不依赖文件存在)
这个函数会处理路径里的..、.和多余的斜杠:
function normalizePath(path) { // 拆分路径,过滤掉空字符串和当前目录. const segments = path.split('/').filter(seg => seg && seg !== '.'); const normalized = []; for (const seg of segments) { if (seg === '..') { // 遇到上级目录..就弹出上一级(如果有的话) normalized.pop(); } else { normalized.push(seg); } } // 重新拼接成标准绝对路径 return '/' + normalized.join('/'); }
第二步:实现相对路径计算逻辑
基于规范化后的路径,找到公共前缀,再生成最终的相对路径:
function getRelativeFilePath(absolutePath, basePath) { // 先对两个路径做规范化处理 const normalizedAbs = normalizePath(absolutePath); const normalizedBase = normalizePath(basePath); // 拆分成目录数组,过滤掉开头的空字符串(因为绝对路径以/开头,split后第一个元素是空) const absSegments = normalizedAbs.split('/').filter(Boolean); const baseSegments = normalizedBase.split('/').filter(Boolean); // 找到最长的公共前缀长度 let commonPrefixLength = 0; while (commonPrefixLength < absSegments.length && commonPrefixLength < baseSegments.length && absSegments[commonPrefixLength] === baseSegments[commonPrefixLength]) { commonPrefixLength++; } // 基础路径剩下的部分需要用..来返回上级目录 const upLevels = baseSegments.length - commonPrefixLength; // 拼接所有..和绝对路径剩下的部分 const relativeSegments = Array(upLevels).fill('..').concat(absSegments.slice(commonPrefixLength)); return relativeSegments.join('/'); }
测试你的示例
// 第一个例子 getRelativeFilePath('/a/b/c/1.txt', '/a/d/e'); // 返回 '../../b/c/1.txt',完全符合预期 // 修正后的第二个例子(原示例路径计算结果不符,应该是下面这个路径) getRelativeFilePath('/a/b/../c/1.txt', '/a/d/e'); // 返回 '../c/1.txt',和你示例结果一致
这样实现下来代码量不大,逻辑也清晰,完全可以直接复用~
内容的提问来源于stack exchange,提问作者vp_arth
相关产品推荐
相关产品推荐

