Open Source, 100% Compatible ln for Windows (and Junction Point library)

We’ve been huge fans of symlinks for forever, and even posted about Windows Vista’s new mklink commandline utility with quite the passion back in 2006 when the ability to create soft-links from the commandline was first added to Windows.

However, there are a few things that have forever irked us about the ln lookalike called mklink.exe:

  • It’s called mklink and not ln. (I mean, you just get can’t get around that fact)
  • The arguments are switched around. `mklink something_doesnt_exist actual_file` is just…….. wrong!
  • By default, mklink will create softlinks and not hardlinks. ln requires the /h flag to create a hardlink.
  • mklink isn’t smart enough to distinguish between files and folders. You need explicitly tell it via the commandline.
  • Even then, mklink has two different switches depending on the type of directory link you want. /D for softlink’d directories, and /J for hardlink’d directories.
  • mklink can’t be used outside of cmd.exe (such as in PowerShell). (Hat tip: Jason)
  • And, of course,  mklink isn’t open source.

So we made our own.

ln-win is available in 32-bit and 64-bit, uses the same syntax, names, switches, and argument ordering as ln on *nix. And pursuant to our promise to contribute more to open source, ln-win and our Junction Point library is 100% open source, freely licensed under the generous terms of the MIT license.

Perhaps more importantly, ln-win contains an open source Junction Point library. While Win32 APIs exist to create symlinks (on Vista and up), there is no API for creating hardlinks of any kind (for files or folders). The NeoSmart JunctionPoint library provides the following APIs:

	bool CreateJunctionPoint(LPCTSTR origin, LPCTSTR junction);
	bool IsDirectoryJunction(LPCTSTR path);
	bool GetJunctionDestination(LPCTSTR path, OUT LPTSTR destination);
	bool DeleteJunctionPoint(LPCTSTR path);

As you can see, the NeoSmart JunctionPoint library provides all the APIs you need both to create and interact with hardlinks. IsDirectoryJunction can be used for both symlinks and hardlinks, making it a snap to make your code symlink/hardlink aware, letting you intelligently avoid cyclic paths and data duplication for any filesystem traversal needs.

Binaries for Windows x86 and x64

ln-win Source Code on GitHub

  • Similar Posts

    Craving more? Here are some posts a vector similarity search turns up as being relevant or similar from our catalog you might also enjoy.
    1. Vista Gets It: Symlinks at Last!
    2. Vista Symlinks Revisited…
    3. Redirecting External Links to Old Downloads
    4. How to import any Linux command into your Windows 10 environment
  • 17 thoughts on “Open Source, 100% Compatible ln for Windows (and Junction Point library)

    1. @neosmart: neat! just tried it out, works great. And the source code is clean, thanks!

      @randomcore: doesn’t look like Hermann’s tool is open source. And it doesn’t use the same syntax as the unix ln, either.

    2. As a sysadmin, I always get frustrated when I forget the order of commandline arguments for mklink. This is awesome!

      Thanks 🙂

    3. someone: that’s correct. If there’s enough demand, we’ll make it work on XP in “backwards-compatibility mode,” i.e. hardlinks only for both files and folders.

    4. Thanks for this! I never could remember the name of the Windows one, let alone it’s syntax.

    5. Thanks for the write,I myself like and support open source but this is my first time encountering In-win and mklink. Another new discovery for me.

    6. This article has a greatly misleading title. It’s hard to claim “100% comatible” when the tool is neither compatible with the most commonly installed version of Windows (XP, with 51% market share as of March 2012 according to http://www.netmarketshare.com), nor POSIX semantics (creating a symlink to a target that doesn’t exist yet will fail, as an example).

    7. @Erik have you tried it? It does create symbolic links to targets that don’t exist. And it’s simply not designed for XP.

      ln -s c:\does_not_exist newsymlink
    8. Mahmoud: I haven’t tried it, but I’ve read the code. So I already know the subtle defects. It does create links to non-existent links, but they are assumed to be directories because the code doesn’t check for INVALID_FILE_ATTRIBUTES on the GetFileAttributes(source) call, but simply bit-checks it against FILE_ATTRIBUTE_DIRECTORY.

      There isn’t really a way to fix this; symlinks on Windows needs to know what they are pointing to at creation-time, which is incompatible with POSIX symlinks.

      Saying that it’s “simply not designed for XP” is IMO just another way of saying that it’s not “100% compatible”, so you’re just making my point here.

      I’m not saying the tool is bad, I’m saying it’s trying to solve something that isn’t possible. It can still be useful to people in the current state, of course.

      The reason why I even stumbled in here, was that this post mislead someone else, and I had to explain that this was not a sufficient solution in our case. So I stand by my comment about the title of this article being misleading; it already lead to someone wasting their time.

    9. Fair point. I had not considered that case.

      Of course, nothing is impossible to fix/work around. In this particular case, you’d need a filesystem driver (a filter might work?) to add a 3rd type of “symbolic link” that would dynamically resolve the type of object it’s pointing at (or not, if the link remains broken) at the time of invocation. A more naïve solution also exists, with using the filename to “guess” whether it’s going to be a directory or a file, too.

      RE Windows XP support… well, I still maintain that’s just being pedantic. Even if it had XP support, you’d then say it’s not a 100% compatible because it doesn’t support Windows 2000 or even Windows NT. I agree, XP is still popular and all our other programs are still written with XP in mind, but that’s just the nature of the beast.

    10. Well, my point is that “100% compatible” is a pretty huge claim. Why claim it in the first place? People are going to get confused about it. For instance, I still don’t understand what aspects of the program that claim refers to. It isn’t compatible with all Windows-versions. And even if it were, it looks to me like it’s not compatible with setups that doesn’t use NTFS. It certainly isn’t compatible with POSIX semantics (I already showed one problem, but there’s more. The argument parsing instantly springs to mind).

      And I would like to point out once again that my criticism isn’t of the tool, I think the limitations of the tool makes sense within the context. My criticism is only with the “100% compatible”-claim in the title of this blog-post.

    Leave a Reply

    Your email address will not be published. Required fields are marked *