How to read a symlink in Node.js
Asked Answered
M

2

7

I want to read a symlink, and get the details of the link itself, not the contents of the linked file. How do I do that in Node, in a cross-platform way?

I can detect symlinks easily using lstat, no problem. Once I know the path of the file, and that it is a symlink though, how can I read it? fs.readFile always reads the target file, or throws an error for reading a directory for links to directories.

There is a fs.constants.O_SYMLINK constant, which in theory solves this on OSX, but it seems to be undefined on both Ubuntu & Windows 10.

Mcdevitt answered 17/8, 2018 at 13:49 Comment(1)
I hope my answer helps, I'm not sure why you would want to read the raw link file on windows / linux.Rhone
R
11

If you have determined that the file is a symlink try this:

fs.readlink("./mysimlink", function (err, linkString) { 
         // .. do some error handling here .. 
         console.log(linkString) 
});

Confirmed as working on Linux.

You could then use fs.realpath() to turn it into a full path. Be aware though that linkString can be just a filename or relative path as well as a fully qualified path so you may have to get fs.realpath() for the symlink, determine its directory part and prefix it to linkString before using fs.realpath() on it.

Rhone answered 17/8, 2018 at 14:13 Comment(6)
Thanks! Yes, I think that's perfectMcdevitt
Regarding the statement above about running fs.realpath() on the symlink first, in my Node.js v10.16.0 it did not return the full path to the symlink. Instead, running fs.realpath() on a symlink returned the full path to the target of the symlink without needing to run fs.readlink() at all. This seems fine for my purposes but seems problematic if someone wants the actual full path to the symlink. This is also the behavior on Python's os.path.realpath().Piselli
On Windows when I point this to a .lnk file, I just get Error: UNKNOWN: unknown error, readlinkAudiophile
@tom I think this is a linux only function. However, are you pointing to the file with or without the extension?Rhone
@Voltaire, I tried both. I ended up creating the links with the command line with mklink /D. It works the same as on Linux then. Friend of mine who's very knowledgable in Windows told me that the .lnk files are actually files storing metadata for the links like arguments and the icons and therefore only work with windows explorer and are not actual links. He told me to use the command line for creating real links and then everything should work as expected, which it does. It's transparent then as it should be,Audiophile
readlink() is not a Unix-only function. It's also implemented for Windows. But only for real symlinks on Windows, which are rarely used and require Admin privileges even to make. The files with .lnk extensions are not real symlinks but are Windows "shortcuts", which are something for Explorer, not for the filesystem, like aliases on the Mac. Cygwin however provides custom versions of all the symlink functions that treats .lnk shortcuts as symlinks. Either because they work on non-NT Windows, because they work on non-NTFS drives, or because they don't need admin privs.Lal
S
1

I've just faced the same issue: sometimes fs.readlink returns a relative path, sometimes it returns an absolute path. (proper error handling not implemented to keep things simple)

const fs = require('fs');
const pathPckg = require('path');

async function getTarLinkOfSymLink(path){
    return new Promise((resolve, reject)=>{
        fs.readlink(path, (err, tarPath)=>{
            if(err){
                console.log(err.message);
                return resolve('');
            }
            const baseSrcPath = pathPckg.dirname(path);
            return resolve( pathPckg.resolve(baseSrcPath, tarPath) );
        });
    });
}

// usage:
const path = '/example/symbolic/link/path';
const tarPath = await getTarLinkOfSymLink(path);

The code works if the symbolic link is either a file or a directory/folder - tested on Linux

Sublittoral answered 7/1, 2020 at 15:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.