如何使用JavaScript从完整路径中获取文件名?

423

有没有一种方法可以获取完整路径中最后一个值(基于'\'符号)?

例子:

C:\Documents and Settings\img\recycled log.jpg

对于这种情况,我只想在JavaScript中从完整路径中获取recycled log.jpg

22个回答

855
var filename = fullPath.replace(/^.*[\\\/]/, '')

这个代码可以处理路径中的 \ 或 / 符号


6
不适用于MAC OSX,使用chrome时会转义\后的字符。 - Pankaj Phartiyal
10
根据这个网站,使用 replace 比起 substr 要慢得多。 substr 可以与 lastIndexOf('/')+1 结合使用:http://jsperf.com/replace-vs-substring - Nate
1
@nickf Nick,我不确定哪里出了问题,但当文件路径只有一个斜杠时,代码对我来说无法工作。Fiddle,尽管对于\\\,它可以正常工作。 - Shubh
2
你能解释一下正则表达式吗? - lesolorzanov
1
无必要的转义字符:/ no-useless-escape - dude
显示剩余8条评论

197

仅出于性能考虑,我测试了这里给出的所有答案:

var substringTest = function (str) {
    return str.substring(str.lastIndexOf('/')+1);
}

var replaceTest = function (str) {
    return str.replace(/^.*(\\|\/|\:)/, '');
}

var execTest = function (str) {
    return /([^\\]+)$/.exec(str)[1];
}

var splitTest = function (str) {
    return str.split('\\').pop().split('/').pop();
}

substringTest took   0.09508600000000023ms
replaceTest   took   0.049203000000000004ms
execTest      took   0.04859899999999939ms
splitTest     took   0.02505500000000005ms

获胜者是 Split and Pop 规则,感谢 bobince


7
根据元讨论,请在其他答案中加入适当的引用。更好地解释您如何分析运行时间也会很有帮助。 - jpmc26
请随意对此版本进行基准测试。应支持Mac和Windows文件路径。path.split(/.*[\/|\\]/)[1]; - tim-montague
3
测试结果有误。substringTest 只搜索正斜杠(/),execTest 只搜索反斜杠(\),而另外两个测试则同时处理这两种斜杠。实际结果已不再相关。请查看此链接:https://jsperf.com/name-from-path - Grief
3
抱歉,@Grief提供的链接已经失效了。 - crthompson

181
在Node.js中,您可以使用Path的解析模块...。
var path = require('path');
var file = '/home/user/dir/file.txt';

var filename = path.parse(file).base;
//=> 'file.txt'

62
如果使用Node.js,您可以直接使用basename函数:path.basename(file) - derpedy-doo
当你使用webpack 5时,要小心寻找答案的人。在webpack 5中,原生模块不再进行polyfill,这对我来说是一个头疼的问题,我一直在努力解决。 - undefined

93

这条路径来自哪个操作系统平台?Windows路径不同于POSIX路径,也不同于Mac OS 9路径和RISC OS路径...

如果它是一个Web应用程序,文件名可能来自不同的平台,那么就没有一个通用的解决方案。然而,一个合理的尝试是同时使用 '\' (Windows) 和 '/' (Linux/Unix/Mac,同时也是Windows的另一种选择) 作为路径分隔符。以下是一个非正则表达式版本,以增加乐趣:

var leafname= pathname.split('\\').pop().split('/').pop();

你可能想要补充一下,经典的MacOS(<= 9)使用冒号分隔符(:),但我不知道是否还有任何浏览器会将MacOS路径转换为POSIX路径,即file:///path/to/file.ext的形式。 - eyelidlessness
4
你可以使用pop()代替reverse()[0]。它也会修改原始数组,但在你的情况下没问题。 - Chetan S
1
我在想我们如何创建一个相应的函数来获取路径。 - Todd Horst
var path = '\Dir2\Sub1\SubSub1'; //path = '/Dir2/Sub1/SubSub1'; path = path.split('\').length > 1 ? path.split('\').slice(0, -1).join('\') : path; path = path.split('/').length > 1 ? path.split('/').slice(0, -1).join('/') : path; console.log(path); - Todd Horst
命名“leafname”源自目录/文件结构名称“Tree”,tree的第一件事是root,最后是leaves => 文件名是tree路径中的最后一件事 => leaf :-) - jave.web

32

Ates,你的解决方案不能防止空字符串作为输入。在这种情况下,它会出现错误:TypeError:/( [^(\\ | / |:)]+)$ /。exec(fullPath)没有属性

Bobince,这是nickf的一个版本,可以处理DOS、POSIX和HFS路径分隔符(以及空字符串):

return fullPath.replace(/^.*(\\|\/|\:)/, '');

4
如果我们要在 PHP 中编写这段 JS 代码,每个 \ 都需要增加一个额外的 \。 - Raj

23
以下这行 JavaScript 代码将会给你文件名。
var z = location.pathname.substring(location.pathname.lastIndexOf('/')+1);
alert(z);

15

另一个例子

var filename = fullPath.split(/[\\\/]/).pop();

这里拆分有一个带有字符类的正则表达式。
这两个字符必须用“\”进行转义。

或者使用数组拆分

var filename = fullPath.split(['/','\\']).pop();

如果需要,这是动态将更多分隔符推入数组的方法。
如果fullPath由您代码中的字符串显式设置,则需要转义反斜杠
例如:"C:\\Documents and Settings\\img\\recycled log.jpg"


1
关于“数组拆分”,我没有看到传递数组作为分隔符列表的选项。实际上,文档说明:“如果分隔符是一个数组,则该数组被强制转换为字符串并用作分隔符。” - mherzog
.split(['/','\\']).split("/,\\") 是一样的,但这绝对不是你想要的。 - Sebastian Simon

12
在Node.js中,您可以使用path.basename方法。了解更多
const path = require('path');
const file = '/home/user/dir/file.txt';

const filename = path.basename(file);
//=> 'file.txt'

12
不需要特别处理反斜杠,大多数答案不处理搜索参数。
现代方法是简单地使用URL API并获取pathname属性。该API将反斜杠规范化为斜杠。请注意,location(在浏览器环境中)也可以工作,但仅适用于当前URL,而不是任意URL。
为了将结果中的%20解析为空格,只需将其传递给decodeURIComponent

const getFileName = (fileName) => new URL(fileName).pathname.split("/").pop();

// URLs need to have the scheme portion, e.g. `file://` or `https://`.
console.log(getFileName("file://C:\\Documents and Settings\\img\\recycled log.jpg")); // "recycled%20log.jpg"
console.log(decodeURIComponent(getFileName("file://C:\\Documents and Settings\\img\\recycled log.jpg"))); // "recycled log.jpg"
console.log(getFileName("https://example.com:443/path/to/file.png?size=480")); // "file.png"
.as-console-wrapper { max-height: 100% !important; top: 0; }

如果你想获取路径中最后一个非空部分(例如从https://example.com/file.png/获取file.png),请在.pop()之前添加.filter(Boolean)
如果你只有一个相对URL,但仍想获取文件名,请使用URL构造函数的第二个参数传递基本来源。 "https://example.com"就足够了:new URL(fileName, "https://example.com")。还可以在fileName前面加上"https://"—— URL构造函数接受https://path/to/file.ext作为有效的URL。

今天我第n次查看了URL API,但我仍然觉得它不够好,因为我没有发现它提供的任何功能是内置的位置对象没有提供的。 - David A. Gray
例如,URL验证:try{ new URL(url); return true; } catch{ return false; }检查URL是否有效。这是使用location不可能的。在此答案中,URL不一定用于当前URL。我不知道如何仅使用location(且无需重定向)轻松获取任意URL的URI组件。另一个问题是搜索参数API:没有location.searchParams,但URLSearchParams对象有有用的方法。此外,location在浏览器之外不存在,但URL可能存在。 - Sebastian Simon
@DavidA.Gray 另外,从规范中可以看到:“警告:Location异类对象是通过IDL、创建后调用JavaScript内部方法以及重写JavaScript内部方法的混合方式定义的。再加上其可怕的安全策略,请在实现此异常时格外小心。” - Sebastian Simon

10

这个答案并不比nickf的答案更加简洁,但是它直接“提取”答案而不是用空字符串替换不想要的部分:

var filename = /([^\\]+)$/.exec(fullPath)[1];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接