7

How can I determine if a file path is absolute? Must work on both Windows and Linux.

mpen
  • 272,448
  • 266
  • 850
  • 1,236

2 Answers2

7

Here my try at doing it with a single function:

function isAbsolutePath($path) {
    if (!is_string($path)) {
        $mess = sprintf('String expected but was given %s', gettype($path));
        throw new \InvalidArgumentException($mess);
    }
    if (!ctype_print($path)) {
       $mess = 'Path can NOT have non-printable characters or be empty';
       throw new \DomainException($mess);
    }
    // Optional wrapper(s).
    $regExp = '%^(?<wrappers>(?:[[:print:]]{2,}://)*)';
    // Optional root prefix.
    $regExp .= '(?<root>(?:[[:alpha:]]:/|/)?)';
    // Actual path.
    $regExp .= '(?<path>(?:[[:print:]]*))$%';
    $parts = [];
    if (!preg_match($regExp, $path, $parts)) {
        $mess = sprintf('Path is NOT valid, was given %s', $path);
        throw new \DomainException($mess);
    }
    if ('' !== $parts['root']) {
        return true;
    }
    return false;
}

I took this from one of my project you might find useful while working with files and paths: dragonrun1/file_path_normalizer

Dragonaire
  • 313
  • 3
  • 7
  • 1
    Can't see any problems with that. Will accept. Thanks! – mpen Jun 24 '16 at 22:14
  • This is a solution to copypaste from a StackOverflow answer. What I would be more interested in is whether there is currently a "winning" or "de facto standard" solution that has established existence outside StackOverflow, like a library that can be installed with composer or something. Is there a "de facto standard" path utilities library? – Szczepan Hołyszewski Dec 29 '17 at 14:09
  • If you look at my answer above I give link to the project I did which is also available through composer. – Dragonaire Jan 02 '18 at 18:27
  • I had trouble with this on Windows - I had to change the root capture group to look allow for backslashes instead of only forward slashes. Old: `$regExp .= '(?(?:[[:alpha:]]:/|/)?)';` New:`(?(?:[[:alpha:]]:[/\\\\]|/)`. Note the use of _4_ backslashes, the first and third are doing PHP level escaping, the second is doing regex level escaping. – HPierce Sep 03 '18 at 00:08
  • If you look at the latest version from my library you'll find I've changed that method a lot and just replace all back-slashes with forward-slashes to start with in the path since windows also allows them. – Dragonaire Sep 05 '18 at 20:19
  • @HPierce, i have copied the entire function and added you fix, but I got a regex error, namely: "missing closing parenthesis at offset". So I have added a little at the end and got it working. Old regex: `(?(?:[[:alpha:]]:[/\\\\]|/)` new: `(?(?:[[:alpha:]]:[/\\\\]|/)?)`. See the `?)` at the end. – Pakspul Jun 20 '22 at 17:06
5

Here's what I've come up with:

function is_absolute_path($path) {
    if($path === null || $path === '') throw new Exception("Empty path");
    return $path[0] === DIRECTORY_SEPARATOR || preg_match('~\A[A-Z]:(?![^/\\\\])~i',$path) > 0;
}

I think that covers all the possible root paths for Windows.

Community
  • 1
  • 1
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 1
    It still breaks for paths that have [wrappers](http://php.net/manual/en/wrappers.php). try 'zlib://c:/dummy/path/' or 'file://c:/dummy/path' – Dragonaire Jun 24 '16 at 21:16
  • @Dragonaire [Node](https://nodejs.org/api/path.html#path_path_isabsolute_path) returns `false` for both those examples too, which I think is the correct answer. We're talking about *file* paths here, not URLs. – mpen Jun 24 '16 at 21:51
  • Guess you need to read the wrapper link I give as they have nothing to do with URLs in and of themselves. You can use them to implement things like ftp around a stream but then you have file:// which does no more then make a local file in a stream resource instead of just a string. The fact that Node(JS) doesn't understand something that is PHP specific doesn't surprise me either ;) – Dragonaire Jun 25 '16 at 22:33
  • @Dragonaire Yes, but that's not the point. It depends on your use case. If I'm accepting file paths from a user, for example, do I want to allow them specify wrapper methods? Probably not. – mpen Jun 27 '16 at 15:44
  • That's one reason I add the option to not allow them in my little library ;) – Dragonaire Jun 28 '16 at 16:24