Use PHP functions in JavaScript

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(/\/[^\/]*\/?$/, '');}
external links: original PHP docs | raw js source

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.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
starmonkey
Feb 15th Permalink

q  Using this function:

dirname("/index.htm")



Gives me

""

Using PHP (4):


echo "
dirname test:".dirname("/index.htm");



Gives me "dirname test:/"

Gravatar
Michael White
11 May '09 Permalink

q  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.

Gravatar
mk.keck
6 Mar '09 Permalink

q  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]

Gravatar
mk.keck
5 Mar '09 Permalink

q  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 ;)

Gravatar
Michael
4 Mar '09 Permalink

q  @ 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'

Gravatar
Kevin van Zonneveld
4 Mar '09 Permalink

q  @ 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.

Gravatar
Michael
3 Mar '09 Permalink

q  [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

Gravatar
Kevin van Zonneveld
29 Apr '08 Permalink

q  @ Philip: Judging by the rexeg, it looks to me like dots are handled just like normal characters. So /etc/vsftpd/../vsftpd.conf should return /etc/vsftpd/..
For relative paths there's the function realpath in PHP. Maybe we should port that as well?

Gravatar
Philip
29 Apr '08 Permalink

q  Question: does it work for things with ../ in it ? Does the PHP version do it, for that matter?

Gravatar
Kevin van Zonneveld
28 Apr '08 Permalink

q  @ Xorax: Cool, thank you!

Gravatar
XoraX
28 Apr '08 Permalink

q  [CODE="php"]
dirname('/dir/test/'); // output /dir
[/CODE]
so :
[CODE="javascript"]
return path.replace(/\\/g,'/').replace(/\/[^\/]*\/?$/, '');
[/CODE]
http://www.xorax.info/
;)


Contribute a New function

More functions

In this category

basename
» dirname
fclose
feof
fgetc
fgetcsv
fgets
fgetss
file
file_exists
file_get_contents
filemtime
filesize
fopen
fpassthru
fread
fscanf
fseek
ftell
pathinfo
pclose
popen
readfile
realpath
rewind

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: @HalfWinter, Paulo Freitas, Andros Peña Romo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !