Logical path function in PHP

2017/12/02 --Like realpath() but don't resolve symlinks
function logicalpath($path) {
    // same as realpath() except keeps logical paths
    if (!file_exists($path)) {
        return False;
    $filename = '';
    if (is_file($path)) {
        $filename = (basename($path));
        $length = strlen($filename);
        $path = substr($path, 0, -$length);
        $filename = '/'.$filename;
    return exec('bash -c "cd '. escapeshellarg($path) .' && pwd -L"').$filename;

I recently needed to be able to resolve the real logical path, similar to realpath() but leaving symlinks intact. I couldn't find an elegant way to do this without shelling out unfortunately. As far as I am aware it is functionally equivalent to realpath().

mac@localhost:~$ mkdir foo
mac@localhost:~$ mkdir bar
mac@localhost:~$ ln -s ../bar foo/
mac@localhost:~$ touch ~/foo/bar/xyzzy.txt
mac@localhost:~$ cd foo/bar
mac@localhost:~/foo/bar$ pwd -L
mac@localhost:~/foo/bar$ pwd -P
mac@localhost:~/foo/bar$ php -a
Interactive mode enabled

php > include '/home/mac/paths.php';
php > echo(realpath('/home/mac/foo/bar/'));
php > echo(logicalpath('/home/mac/foo/bar/'));
php > echo(logicalpath('/var/tmp/../../home/mac/foo/bar/'));
php > echo(logicalpath('/var/tmp/../../home/mac/foo/bar/xyzzy.txt'));

GitHub Gist

NethackA Job For a Sunday