JavaScript dirname
Returns the directory name component of the path
1 2 3 4 56 7 8 9 1011 12 13 14 1516 | function dirname (path) { // Returns the directory name component of the path // // version: 1008.1718 // discuss at: http://phpjs.org/functions/dirname // + original by: Ozh // + improved by: XoraX (http://www.xorax.info) // * example 1: dirname('/etc/passwd'); // * returns 1: '/etc' // * example 2: dirname('c:/Temp/x'); // * returns 2: 'c:/Temp' // * example 3: dirname('/dir/test/'); // * returns 3: '/dir' return path.replace(/\\/g,'/').replace(/\/[^\/]*\/?$/, '');} |
Examples
» Example 1
Running
1 | dirname('/etc/passwd'); |
Should return
1 | '/etc' |
» Example 2
Running
1 | dirname('c:/Temp/x'); |
Should return
1 | 'c:/Temp' |
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 dirname goodness in JavaScript.
Hey,
I was working with the __DIR__() and __FILE__() stuff again today and I ran across a bug in this function.
If you pass something like 'filename.js' to this function in IE7 it will return 'filename.js' instead of '.'
To work around the behavior of IE I modified the function to the following:
[CDOE]
function dirname(path){
var dir = path.replace(/\\/g,'/').replace(/\/[^\/]*\/?$/,'');
return (dir && !dir == path) ? dir : '.';
}
[/CODE]
The only change is to store the result of the regex in a variable and then check to see if the result is empty or if the result is equivalent to the original input.
The result of the regex should only be equal to the original input if using IE7 (6/8????) AND that original input was just the file name and contained no slashes or directory components.
Hi again,
sorry: in last post there are some mistakes.
If your path leaves outside the window.location.href the path may be wrong.
I've never a seen a system, where you can leave the doc-root ;)
Now here's the final function and I hope it would be nice, that realpath is proted php.js ;)
[CODE="Javascript"]
/**
* Expands all symbolic links and resolves references
* to '/./', '/../' and extra '/' characters in the
* input 'path' and return the canonicalized absolute
* pathname
* @param {String} path: the relative pathname
* Note:
* The returned path is an url like e.g.
* 'http://yourhost.tld/path/'
*/
function realpath(path) {
var p = 0, arr = [];
/* Save the root, if not given */
var r = window.location.href;
/* Avoid input failures */
path = (path + '').replace('\\', '/');
/* Check if there's a port in path (like 'http://') */
if (path.indexOf('://') !== -1) {
p = 1;
}
/* Ok, there's not a port in path, so let's take the root */
if (!p) {
path = r.substring(0, r.lastIndexOf('/') + 1) + path;
}
/* Explode the given path into it's parts */
arr = path.split('/');
/* The path is an array now */
path = [];
/* Foreach part make a check */
for (var k in arr) {
/* This is'nt really interesting */
if (arr[k] == '.') {
continue;
}
/* This reduces the realpath */
if (arr[k] == '..') {
/* But only if there more than 3 parts in the path-array.
* The first three parts are for the uri */
if (path.length > 3) {
path.pop();
}
}
/* This adds parts to the realpath */
else {
/* But only if the part is not empty or the uri
* (the first three parts ar needed) was not
* saved */
if ((path.length < 2) || (arr[k] !== '')) {
path.push(arr[k]);
}
}
}
/* Returns the absloute path as a string */
return path.join('/');
}
/**
* EXAMPLES
* perhabs your window.location.href returns something like this:
* 'http://www.myserver.com/js/rp/my.html'
*/
// Example 1
path = 'this/is/../a/test/.//is';
path = realpath(path);
// result: 'http://www.myserver.com/js/rp/this/a/test/is'
// Example 2
path = '../this/is/../a/test/.//is';
path = realpath(path);
// result: 'http://www.myserver.com/js/this/a/test/is'
// Example 3
path = '../../../this/is/../a/test/.//is';
path = realpath(path);
// result: 'http://www.myserver.com/this/a/test/is'
// note: you can't leave your server ;)
[/CODE]
My previous function was a bit overkilled so I've made a better one:
[CODE="Javascript"]
function realpath(path) {
var p = 0, arr = [];
var r = window.location.href;
if (path.indexOf('://') !== -1) {
p = 1;
}
if (!p) {
path = r.substring(0, r.lastIndexOf('/') + 1)
+ path;
}
arr = path.split('/');
path = [];
for (var k in arr) {
if (arr[k] == '.') {
continue;
}
if (arr[k] == '..') {
path.pop();
} else {
if (k < 2 || arr[k] !== '') {
path.push(arr[k]);
}
}
}
return path.join('/');
}
[/CODE]
How it works:
[CODE="Javascript"]
url = 'this/is/../a/./test/.///is';
url = realpath(url);
alert(url);
[/CODE]
will alert something like:
'http://yourhost.tld/yourpath/this/a/test/is'
I hope this would be good reason for simulate php's realpath function in javascript ;)
@ Kevin: jepp I understand.
So here's a newer function:
[CODE="Javascript"]
function realpath(path) {
var base = '', port = '', parts = [];
/**
* Split the given path into port and path
*/
function urisplit(p) {
if (p.substring(0, 7).toLowerCase() === 'http://' || p.substring(0, 7).toLowerCase() === 'file://' || p.substring(0, 7).toLowerCase() === 'ftps://') {
base = p.substring(7, p.length);
port = p.substring(0, 7);
} else if (p.substring(0, 8).toLowerCase() === 'https://') {
base = p.substring(8, p.length);
port = p.substring(0, 8);
} else if (p.substring(0, 6).toLowerCase() === 'ftp://') {
base = p.substring(6, p.length);
port = p.substring(0, 6);
}
}
/**
* Make a relative path to an absolute
* @param {String} s: source path
* @param {String} r: relative path
*/
function abspath(s, r) {
var a = 0, add = '', arr = [], cnt = 0, num = 0, ret = '';
if (r.substring(0, 2) == './') {
r = r.substring(2, r.length);
}
if (r !== '') {
arr = r.split('/');
num = arr.length;
for (a = 0; a < num; a++) {
if (arr[a] !== '') {
if (arr[a] !== '..') {
add += arr[a] + '/';
} else {
cnt++;
}
}
}
}
if (s !== '') {
arr = s.split('/');
num = (arr.length - cnt);
for (a = 0; a < num; a++) {
if (arr[a] !== '') {
ret += arr[a] + '/';
}
}
ret += add;
}
return ret;
}
/* check for the port */
urisplit(path);
/* path has no port: perhabs relative */
if (port == '') {
base = window.location.href;
base = base.substring(0, base.lastIndexOf('/')) + '/';
urisplit(base);
base = abspath(base, path);
}
else {
alert(base);
base = path.substring(0, path.lastIndexOf('/')) + '/';
urisplit(base);
}
path = port + base;
return path;
}
[/CODE]
But this would only work if your path like something './../path' or './path/' or '/path' or simple 'path'
@ Michael: In php, realpath is used to make an absolute path, based on a relative one:
e.g.: '../' becomes /tmp/ if your pwd is /tmp/abc/
If you'd want to do that in javascript, you'd have to base realpath on the location.href or something.
I haven't figured out yet if that would be useful / desirable or not.
[CODE="Javascript"]
function realpath(path) {
return path.substring(0, path.lastIndexOf('/')) + '/';
}
[/CODE]
gets for me the realpath for any file.
dirname('/myfiles/cache/temp/');
should return '/myfiles/cache/temp/', so php does it.
Or my I wrong?
But dirname('/myfiles/cache/temp/thefile.txt');
return the right dirname.
Regards Michael


starmonkey
Feb 15th
dirname("/index.htm")Gives me
""
Using PHP (4):
Gives me "dirname test:/"