JavaScript basename
Returns the filename component of the path
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 | function basename (path, suffix) { // Returns the filename component of the path // // version: 910.820 // discuss at: http://phpjs.org/functions/basename // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Ash Searle (http://hexmen.com/blog/) // + improved by: Lincoln Ramsay // + improved by: djmix // * example 1: basename('/www/site/home.htm', '.htm'); // * returns 1: 'home' // * example 2: basename('ecra.php?p=1'); // * returns 2: 'ecra.php?p=1' var b = path.replace(/^.*[\/\\]/g, ''); if (typeof(suffix) == 'string' && b.substr(b.length-suffix.length) == suffix) { b = b.substr(0, b.length-suffix.length); } return b;} |
Examples
» Example 1
Running
1 | basename('/www/site/home.htm', '.htm'); |
Should return
1 | 'home' |
» Example 2
Running
1 | basename('ecra.php?p=1'); |
Should return
1 | 'ecra.php?p=1' |
Dependencies
No dependencies, you can use this function standalone.
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have basename goodness in JavaScript.
Hello there.
I would like to report that basename should stripdown what's in front of the ?. By applying basename to a url like this:
ecra.php?p=1
It should return "ecra.php" only.
I've tested the following way:
1 2 | var path = window.location.href; console.log(basename(path)); |
Please note:
With window.location.pathname this issue does not apply.
@Kevin: Sweet! Thanks for handling that! Yes, I think it should work just fine for content... Btw, while there's no harm in it, we don't strictly need to "dual license" since the MIT license is compatible with GPL (though not vice versa)--you can just use MIT and it will work for GPL users, though I guess maybe it avoids GPL users having to copy-and-paste the MIT clause info...
@ Brett Zamir: I manually changed the license now. It's the same as PHP.JS'. Will this license work for content as well as code you think?
@Albert Martin, Thanks for offering. Although we only intend to use functions in the library which adhere to PHP behavior (unless it seems to warrant a configuration which can be changed with ini_set()), you might consider adding your function to http://phpjs.org/wiki . Kevin, it looks like by your removing the specific license, Mediawiki has defaulted to GNU Free Documentation License for the wiki. Do you recall if there was a way to configure it otherwise?
I needed also to remove the extension, no matter what filetype it is. So if you set suffix==true, it removes any, not the one specified:
1 2 3 4 56 7 8 9 10 | function basename(path, suffix) { //... var b = path.replace(/^.*[\/\\]/g, ''); if (typeof(suffix) == 'string' && b.substr(b.length-suffix.length) == suffix) { b = b.substr(0, b.length-suffix.length); } else if (suffix == true && b.indexOf('.') != -1) { b = b.substr(0, b.lastIndexOf('.')); } return b; } |
@ Nate: Thanks a lot Nate! I did struggle to get the regexes to work though (syntax issues). I finally felt like taking a completely different approach (I hope you don't mind man), and by means of an experiment, I took a look at the original php5 C code and tried to recreate it from there.
Of course I kept the credit for your original intact!
Hi. I created a pathinfo() function.
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 | function pathinfo(path, options) { var re = /(([^\\/]*?)(?:\.([^.]*))?)$/; var re2 = /(.*)[\\/]/; var path_arr = re.exec(path); var dir_arr = re2.exec(path); // To be PHP compatible, no directory becomes "." if (dir_arr == null || dir_arr == "") dir_arr = ["","."]; var path_obj = {dirname:dir_arr[1],basename:path_arr[0],extension:path_arr[3],filename:path_arr[2]}; if (typeof options == "undefined") { if (path_obj.extension == "" && path_obj.filename.slice(-1) != ".") { // To be PHP compatible, if there is no dot (.) in the name, the extension value is not set. delete path_obj.extension; } return path_obj; } else { switch (options) { case "PATHINFO_DIRNAME": return path_obj.dirname; case "PATHINFO_BASENAME": return path_obj.basename; case "PATHINFO_EXTENSION": return path_obj.extension; case "PATHINFO_FILENAME": return path_obj.filename; } } } |
example 1: pathinfo("/www/htdocs/index.html");
returns 1: {dirname:"/www/htdocs",basename:"index.html",extension:"html",filename:"index"}
1 | b.substr(-suffix.length) |
doesn't work in ie because him doesn't allow negative values as start index. To solve that the solution is:
1 | b.substr(b.length-suffix.length) |
Fixed Function (Sorry, now yes):
1 2 3 4 56 7 8 9 1011 12 13 14 | function basename(path, suffix) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Ash Searle (http://hexmen.com/blog/) // + improved by: Lincoln Ramsay // * example 1: basename('/www/site/home.htm', '.htm'); // * returns 1: 'home' var b = path.replace(/^.*[\/\\]/g, ''); if (typeof(suffix) == 'string' && b.substr(b.length-suffix.length) == suffix) { b = b.substr(0, b.length-suffix.length); } return b; } |
1 | b.substr(-suffix.length) |
To solve that the solution is:
1 | b.substr(b.length-suffix.length) |
Fixed Function:
1 2 3 4 56 7 8 9 1011 12 13 14 | function basename(path, suffix) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Ash Searle (http://hexmen.com/blog/) // + improved by: Lincoln Ramsay // * example 1: basename('/www/site/home.htm', '.htm'); // * returns 1: 'home' var b = path.replace(/^.*[\/\\]/g, ''); if (typeof(suffix) == 'string' && b.substr(-suffix.length) == suffix) { b = b.substr(0, b.length-suffix.length); } return b; } |
The regular expression is not ECMAScript-262 compliant.
It should be:
1 | var b = path.replace(/^.*[\/\\]/g, ''); |
ECMAScript does not allow / to appear anywhere in a regular expression literal unless it is escaped by the \ character.
1
2
3
4
56
7
| function rand(min, max) { if(max) { return Math.floor(Math.random() * (max - min + 1)) + min; } else { return Math.floor(Math.random() * (min + 1)); } } |
I've fixed a couple of bugs in your current implementation: suffix should be optional, and basename should work for partial paths (e.g. basename("foo.txt" ".txt") should return "foo")
1
2
3
4
56
7
| function basename(path, suffix) { var b = path.replace(/^.*[/\\]/g, ''); if (typeof(suffix) == 'string' && b.substr(-suffix.length) == suffix) { b = b.substr(0, b.length-suffix.length); } return b; } |


Kevin van Zonneveld
8 Oct '09
This may not make a whole lot of sense from the browser point-of-view; but we also have to consider other JavaScript platforms like V8, rhino, and stuff built on that like node.js
This is the one of the reasons we chose to always stick with PHP's implementation. At least developers know what to expect; and in theory you should be able to run PHP code in PHP.JS without worrying about different implementations & stuff blowing up in your face.
So I'm sorry to say Pedro, you're going to have to parse this like you'd otherwise have to in PHP as well.