36

UNIX absolute path starts with '/', whereas Windows starts with alphabet 'C:' or '\'. Does node.js has a standard multiplatform function to check if a path is absolute or relative ?

Manuel Di Iorio
  • 3,051
  • 5
  • 22
  • 28

6 Answers6

52

Since node version 0.12.0 you can use the path.isAbsolute(path) function from the path module.

i.e:

var path = require('path');
if(path.isAbsolute(myPath)) {
    //...
}
Chris Arnesen
  • 1,177
  • 1
  • 9
  • 12
chresse
  • 4,049
  • 2
  • 24
  • 37
  • 3
    note that isAbsolute seems to return true for any path that starts with /, whether on Windows or Mac (not sure about *nix) – Alexander Mills Mar 27 '16 at 03:00
  • As Alexander Mills pointed out, this answer is wrong. If your relative path starts with a `/` (as all relative paths usually do) then this method will return true, which is wrong. I don't know why it was selected as the correct answer, this is dangerous and makes SO unreliable. – Sprout Coder Jul 05 '18 at 10:53
  • 4
    @SproutCoder This answer is correct. Maybe you're thinking of relative paths in the sense of http URLs? The Node.js utility `path.isAbsolute` is meant to be used for filesystem paths where an "absolute path" by definition starts with a slash. See http://www.linfo.org/path.html, for example. – Chris Arnesen Nov 21 '18 at 07:33
  • 1
    Be aware that `isAbsolute`, when handed paths beginning with `~` on unix or unix-like systems, will return `false`. While those paths are indeed relative to the current user's user directory, they are not relative to the *current* directory, so changing directories doesn't affect what they resolve to. In this sense, those paths are absolute, which could be surprising to some people. – ErikE May 07 '19 at 00:39
10

You could use

path.resolve(yourPath)===yourPath

If your path isn't normalized, use

path.resolve( yourPath ) == path.normalize( yourPath )
Denys Séguret
  • 335,116
  • 73
  • 720
  • 697
  • 3
    There's also a isAbsolute function in the source even if I don't find it in docs and it doesn't seem to be available : https://github.com/joyent/node/blob/master/lib/path.js#L206 – Denys Séguret Feb 11 '14 at 10:24
  • Yep, I don't know why there isn't in the doc but for now I think that I will use your response, for security. – Manuel Di Iorio Feb 11 '14 at 10:32
  • 2
    The function is in fact in unstable (0.11) but not in the last stable. – Denys Séguret Feb 11 '14 at 11:27
  • 3
    This doesn't work if `yourPath` isn't already normalized (eg: it doesn't work with `///a//..//b//`. The corrent solution is: `path.resolve( yourPath ) == path.normalize( yourPath )` – peoro Jun 14 '14 at 03:27
  • This answer is a bit ambiguous. What does this check prove? – krex Dec 19 '14 at 11:10
  • I believe the following is more robust: function isAbsolute(p) { return path.normalize(p + '/') === path.normalize(path.resolve(p) + '/'); } – TomDotTom Jun 08 '15 at 16:37
9

As commented to dystroy's answer, the proposed solutions don't work if an absolute path is not already normalized (for example the path: ///a//..//b//./).

A correct solution is:

path.resolve(yourPath) === path.normalize(yourPath)

As Marc Diethelm suggests in the comments, this has still some issues, since path.resolve removes trailing slashes while path.normalize doesn't.

I'm not sure how these function exactly behave (as you can read in the comments), anyway the following snippet seem to work fine at least in Linux environments:

path.resolve(yourPath) === path.normalize(yourPath).replace( RegExp(path.sep+'$'), '' );
Community
  • 1
  • 1
peoro
  • 24,051
  • 18
  • 90
  • 141
  • 1
    However since `normalize` preserves trailing slashes your solution needs to be enhanced. `path.resolve(_yourPath) === path.normalize(_yourPath).replace(/[\/|\\]$/, '')`, will work reliably. – Marc Diethelm Sep 09 '14 at 21:33
  • @MarcDiethelm: you're very right, I never noticed. I'll try to fix the answer taking into account your suggestion! Anyway your solution still doesn't work perfectly, for example it fails with `'/\\'`. Is there any specific reason to remove trailing backslashes? Is it to support windows paths or what else? – peoro Sep 13 '14 at 01:30
  • exactly checking for a trailing backslash is need on Windows. re: it fails with '/\\'. I don't understand, can you elobarate? Is that supposed to be a path you test for?! – Marc Diethelm Sep 16 '14 at 13:04
  • @MarcDiethelm: yes, exactly. I'm running Node on a Linux machine. If I pass to your function the `'/\\'` string, `path.resolve('/\\')` returns `'/\\'`, while `path.normalize('/\\').replace(/[\/|\\]$/, '')` returns `'/'`. The line I added to this response seems to work fine for me on Linux, but might be other issues (maybe on Windows?) – peoro Sep 16 '14 at 13:24
  • The path `'/\\'` seems like a real edge case for me. Maybe try unescaping first? I'm not a fan of invoking the RegExp constructor with all its overhead here. `path.sep` looks nice at first. But basically we just want to remove ANY (Windows or else) trailing slashes before comparing. Here's my amended version that works for a root `'/'` path too: `path.resolve(yourPath) === path.normalize(yourPath).replace(/(.+)([\/|\\])$/, '$1')`. – Marc Diethelm Sep 16 '14 at 14:02
  • This does not work with node v0.10.35 on Windows. If you have an absolute path without drive letter, this will fail because `path.normalize()` does not prepend drive letter. – vulcan raven Jan 14 '15 at 10:04
3

This is a little convoluted, but the most robust way I've found using just the (pre node 0.12.0) path module

function isAbsolute(p) {
    return path.normalize(p + '/') === path.normalize(path.resolve(p) + '/');
}

It should be noted that path.isAbsolute exists from node 0.12.0 onwards.

TomDotTom
  • 4,901
  • 3
  • 32
  • 33
1

I have no idea about node.js, but you can see the source of path.js in github: https://github.com/joyent/node/blob/master/lib/path.js

You can see:

// windows version
exports.isAbsolute = function(path) {
    var result = splitDeviceRe.exec(path),
    device = result[1] || '',
    isUnc = device && device.charAt(1) !== ':';
    // UNC paths are always absolute
    return !!result[2] || isUnc;
};

And:

// posix version
exports.isAbsolute = function(path) {
    return path.charAt(0) === '/';
};
Javier Ros
  • 2,891
  • 2
  • 17
  • 36
-1
    isRelative(url){
        return (/^(\.){1,2}(\/){1,2}$/.test(url.slice(0,3)) ||
        /(\/){1,2}(\.){1,2}(\/){1,2}/.test(url)); 
    }

This makes it easy to check whether a path is relative despite of absence of node path module API.

(/^(\.|~){1,2}(\/){1,2}$/.test(url.slice(0,3))

this part checks if the path string starts with the "./" or "../" or "~/". If it does, Boolean true is returned. Otherwise the next test is executed.

/(\/){1,2}(\.){1,2}(\/){1,2}/.test(url)

This just checks if the path string has either "/./" or "/../". and returns true on any and false on neither.

If any of the two tests is true then the path string is relative.

For windows.

    isRelative(url){
        return (/^(\.){1,2}(\\){1,2}$/.test(url.slice(0,3)) ||
        /(\\){1,2}(\.){1,2}(\\){1,2}/.test(url)); 
    }
  • 1
    Please Explain what you did. – Abhishek Pandey Dec 26 '16 at 06:03
  • How can you define paths starting with `~` as relative? They may be relative, but not to the current directory. It seems like there are really three states and `isAbsolute` is a bad function because it misleads. Paths starting with `~` are stable and don't change depending on the current directory; in this sense they are absolute... – ErikE May 07 '19 at 00:36