56

Recent NTFS and Windows implement symlinks:

  • NTFS junction point can be used as directory symlink since NTFS 3.0 (Windows 2000) using linkd or junction tools.
  • NTFS symbolic link can also be used as symlink (for both file and directory) since Windows Vista using mklink tool.

But on Cygwin 1.7 (installed on Windows 7), ln -s creates a text file.

on Cygwin:

$ ln -s -v target mylink
`mylink' -> `target'

on MinGW (or your favorite editor):

$ cat mylink
!<symlink>ÿþt a r g e t 

Is it possible to tell Cygwing to use NTFS junction point or NTFS symbolic link?

other question: Is this available on MinGW?

Anthony Geoghegan
  • 11,533
  • 5
  • 49
  • 56
oHo
  • 51,447
  • 27
  • 165
  • 200

5 Answers5

90

⸻⸻  Short answer  ⸻⸻

Define environment variable:

CYGWIN=winsymlinks:nativestrict

As pointed out by mwm you may also have to go to the settings or to run as Administrator. See the Notes section.

⸻⸻  Long answer  ⸻⸻

Default Cygwin symlinks are just regular files

By default Cygwin creates text files as workaround for Windows symlink flaw. These files are not really symlinks. Almost all Windows programs do not considers these files as symlinks.

Native symlinks are available on recent Windows versions

Recent NTFS and Windows implement symlinks:

  • NTFS junction point can be used as directory symlink since NTFS 3.0 (Windows 2000) using linkd or junction tools.
  • NTFS symbolic link can also be used as symlink (for both file and directory) since Windows Vista using mklink tool.

Cygwin can create native NTFS symlinks

Simplified extract of the Cygwin documentation:

Symbolic links

[...]

Cygwin creates symbolic links potentially in multiple different ways:

  • The default symlinks are plain files containing a magic cookie followed by the path to which the link points. [...]

  • The shortcut style symlinks are Windows .lnk [...] created if the environment variable CYGWIN [...] is set to contain the string winsymlinks or winsymlinks:lnk. [...]

  • Native Windows symlinks are only created on Windows Vista/2008 and later, and only on filesystems supporting reparse points. Due to to their weird restrictions and behaviour, they are only created if the user explicitely requests creating them. This is done by setting the environment variable CYGWIN to contain the string winsymlinks:native or winsymlinks:nativestrict. [...]

  • On the NFS filesystem, Cygwin always creates real NFS symlinks.

Configuring Cygwin

Cygwin User's Guide presents variable CYGWIN and option winsymlinks:

The CYGWIN environment variable is used to configure many global settings [...]. It contains the options listed below, separated by blank characters. [...]

  • [...]

  • [...]

  • [...]

  • [...]

  • winsymlinks:{lnk,native,nativestrict} - if set to just winsymlinks or winsymlinks:lnk, Cygwin creates symlinks as Windows shortcuts with a special headerand the R/O attribute set.

    If set to winsymlinks:native or winsymlinks:nativestrict, Cygwin creates symlinks as native Windows symlinks on filesystems and OS versions supporting them. If the OS is known not to support native symlinks (Windows XP, Windows Server 2003), a warning message is produced once per session.

    The difference between winsymlinks:native and winsymlinks:nativestrict is this: If the filesystem supports native symlinks and Cygwin fails to create a native symlink for some reason, it will fall back to creating Cygwin default symlinks with winsymlinks:native, while with winsymlinks:nativestrict the symlink(2) system call will immediately fail.

CYGWIN=winsymlinks:native
always creates a link but uses a Cygwin fall-back when target does not exists

on Cygwin:

$ export CYGWIN="winsymlinks:native"
$ ln -s -v target mylink
`mylink' -> `target'
$ echo content > target

on MinGW:

$ cat mylink
content

People using both Windows and Cygwin programs may have issues when a symlink is created as a dummy file (Cygwin fallback when target is missing)...

CYGWIN=winsymlinks:nativestrict
always uses native-Windows symlink but fails when target does not exist

on Cygwin:

$ export CYGWIN="winsymlinks:nativestrict"
$ rm -f  a b
$ ln -sv a b
ln: failed to create symbolic link `b': No such file or directory
$ touch    b
$ ln -sv a b
ln: failed to create symbolic link `b': File exists
$ rm b
$ touch a
$ ln -sv a b
`b' -> `a'

Because nativestrict requires the target exists before the symlink creation, some commands/scripts may fail when creating a link.

Notes

Since Windows 10 build 14972, native NTFS symlinks are available in a non-elevated shell by enabling the Developer Mode in the Developer Settings. Reference: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/

In older versions, only administrators have the ability to create native NT symlinks so under Windows UAC, the Cygwin terminal emulator (mintty) should be run with elevated privileges (right-click the shortcut and choose Run as Administrator or set the mintty shortcut property, Advanced → Run as Administrator).

Special thanks to Guria, Spooky and Gene Pavlovsky for their contributions.

oHo
  • 51,447
  • 27
  • 165
  • 200
  • 2
    I've just upvoted this very informative answer. I also added a suggested edit that users with UAC enabled should run mintty with elevated privileges to be able to create native NT symlinks. – Anthony Geoghegan Jul 08 '14 at 16:03
  • 1
    export CYGWIN="winsymlinks:nativestrict" worked for me in Windows 8 – aqavi_paracha Jan 05 '16 at 08:26
  • 2
    For MSYS2, uncomment `set MSYS=winsymlinks:nativestrict` in `/msys2_shell.bat`. – mkjeldsen Mar 06 '16 at 07:36
  • 1
    This didn't work on my system. The only way was through `cmd /c ...` – CMCDragonkai Mar 24 '16 at 14:28
  • Hi @CMCDragonkai. Thanks for your feedback but I do not know what to say as I do not have same issue. Please tell me what to update in the answer. Cheers ;-) – oHo Mar 24 '16 at 16:24
  • 2
    Inaccurate info on what `nativestrict` means. Quoting the [Cygwin User Guide](https://cygwin.com/cygwin-ug-net/using-cygwinenv.html): *The difference between winsymlinks:native and winsymlinks:nativestrict is this: If the filesystem supports native symlinks and Cygwin fails to create a native symlink for some reason, it will fall back to creating Cygwin default symlinks with winsymlinks:native, while with winsymlinks:nativestrict the symlink(2) system call will immediately fail.* Personally I'm using `nativestrict` and didn't have any fails so far. – Gene Pavlovsky Apr 23 '16 at 20:34
  • Thank you @GenePavlovsky for your feedback :-) I have reworked the answer. However I do not have Cygwin on my computer for the moment (only native Linux). As soon as I install Cygwin, I will check again the snippets. What do you suggest? Cheers :-) – oHo Jun 07 '16 at 21:28
  • 1
    @olibre I've since switched to `native`, because in `nativestrict` mode attempting to create a symlink to non-existent file. E.g. I'm using Gentoo's `run-crons` script in Cygwin, that script creates a lockfile pointing to the current PID (`$$`), that fails in `nativestrict` mode. In `native` mode, it creates a Cygwin (non-native) symlink. I think this is a strange behavior and tried to report it as a bug on Cygwin mailing list, but it was dismissed. You can use that peculiarity to test `ln -s moo link` (assuming `moo` doesn't exist) will fail on `nativestrict` only. – Gene Pavlovsky Jun 09 '16 at 08:13
  • Thank you @GenePavlovsky for your feedback :-) I am glad that `native` enables you to use `run-crons` script. I suppose this may be a design bug in NTFS or Windows internal stuff... Cheers ;-) – oHo Jun 09 '16 at 13:38
  • No, that's Cygwin's chosen behavior. Windows' `mklink` command can create such *broken* links without error. – Gene Pavlovsky Jun 10 '16 at 14:13
  • Thank you @GenePavlovsky very much. I will update my answer. Cheers ;-) – oHo Jun 11 '16 at 13:51
  • It only works for me if it is run as administrator bash – mwm Feb 05 '17 at 01:01
  • You can set up permissions for creating symlinks, so you don't have to run as administrator. See: https://superuser.com/questions/124679/how-do-i-create-a-link-in-windows-7-home-premium-as-a-regular-user?answertab=votes#125981 – Kevin Jul 25 '17 at 08:01
  • On Windows, you might always want to use `nativestrict`, because you don't want Cygwin to fall back to the default behavior at all. – MC Emperor Jun 12 '18 at 11:04
  • 1
    I wish the part about being unable to create symlinks that point to targets that don't exist was featured a little better or reworded slightly because I missed it and then went down a rabbit hole leading me right back here. @GenePavlovsky You were the light at the end of the long tunnel - unfortunately, the Cygwin team didn't see it that way: https://sourceware.org/ml/cygwin/2016-04/msg00658.html – EchoLynx Aug 08 '19 at 21:30
  • Hi @EchoLynx. I need your help to improve my old original answer (2013). I am using Ubuntu at home and Fedora at work. My last computer on Windows was Windows 7. What should I change in this answer to reflect recent changes? Cheers, have fun – oHo Aug 27 '19 at 23:00
  • 1
    @oHo On Windows 10, enable _Developer Mode_ in _Developer Settings_ to be able to creative native NTFS symlinks in a non-elevated shell. Reference: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ – Gene Pavlovsky Jun 29 '22 at 13:24
  • 1
    Thank you @GenePavlovsky I have just updated the answer. Have a nice day – oHo Sep 27 '22 at 00:23
7

The accepted answer is right, two little side notes.

If you only care about the symlinks you create yourself on the command line, install cygutils-extra package, it includes a winln command, which has the same syntax as ln, but creates native Windows links. Create an alias: alias ln=winln (only works in interactive shell), or even replace the ln file with winln (works in shell scripts as well) - but it might get overwritten the next time coreutils package is updated.

I've only found out it's possible to use native symlinks when I already had Cygwin installed, and added some symlinks by myself as well. So after I set CYGWIN=winsymlinks:native as my system environment variable, I wanted to convert all the existing non-native links to native. Here's what I did.

Just in case, back up your entire Cygwin directory first.

Find all symlinks and save the list to /links file: cd /; find . -regextype egrep -regex './(dev|proc|mnt|cygdrive)' -prune -o -type l -print >links

Review links. Create a tar archive with all the links: tar c --files-from=links >links.tar

Extract the tar archive: tar x --files-from=links <links.tar Since native symlinks are now enabled, tar will overwrite the old Cygwin's symlinks with native symlinks.

Clean up: rm -f links links.tar

P.S. At first I used CYGWIN=winsymlinks:nativestrict, but then I found out that in this mode, ln -s target link fails if target doesn't exist. By contrast, native will create a Cygwin (non-native) symlink link pointing to the nonexistent target - this matches the behavior of ln on UNIX systems. In rare cases, nativestrict can break some programs or scripts, for example Gentoo run-crons script uses a lockfile which is a symlink pointing to the PID of the running process. In nativestrict mode the script stopped working, because it could no longer create the lockfile. Note: run-crons is a crontab helper script on Gentoo Linux, adding support for cron.{hourly,daily,weekly,monthly}/ dirs, it works very well with Cygwin.

Gene Pavlovsky
  • 1,515
  • 17
  • 14
  • While this does work (and first we need `editrights -u $USER -a SeCreateSymbolicLinkPrivilege`), this kind of symlink is not exactly the same as the symlink created by `mklink`. Basically CMD's `mklink` doesn't respect that privilege setting and CMD's `mklink` properly sets the type of file to ".symlink", while `winln` doesn't do this. The effect is basically that the symlinks actually look like symlinks when rendered by Windows Explorer and by Cygwin's `ls`, they know it to be a windows symlink when using `mklink`. – CMCDragonkai Apr 24 '16 at 09:45
  • Are you talking about winln or the symlinks created by tar with `CYGWIN=winsymlinks:nativestrict`. I didn't really use winln much, so can't comment, but in the latter case symlinks created by Cygwin look like symlinks in Explorer etc. – Gene Pavlovsky Apr 24 '16 at 10:06
  • I'm talking about `winln`. Just tried it just then. The `CYGWIN=winsymlinks:nativestrict` didn't work at all for me before. – CMCDragonkai Apr 24 '16 at 10:07
  • Ok, I've just tried `mklink fzf-mklink fzf`, `winln -s fzf fzf-winln`, `ln -s fzf fzf-ln` (winsymlinks:nativestrict is set). All three links created show as `.symlink` type in Explorer and point to the same file, fzf. The only difference I can see is mklink-created link is owned by `BUILTIN\Administrators`, while both Cygwin-created links are owned by `Alpha\root` (the current user). Does `CYGWIN=winsymlinks:nativestrict` work for you now, or not? If not, how do you define that variable? – Gene Pavlovsky Apr 24 '16 at 10:45
  • @CMCDragonkai On Windows 10, enable _Developer Mode_ in _Developer Settings_ to be able to creative native NTFS symlinks in a non-elevated shell. Reference: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ – Gene Pavlovsky Jun 29 '22 at 13:26
4

Since @olibre answer didn't work for me. I just created a shell function.

: '
mklink - Create NTFS (Windows) links that is usable by Windows and Cygwin

Usage: mklink [/D | /H | /J] <link-path> <target-path>

Options:
    /D    Directory Symbolic Link
    /H    Hardlink
    /J    Directory Junction (you should prefer /D)

With no options, it creates a NTFS file symlink.
'
mklink () {

    if [ "$#" -ge "3" ]; then
        cmd /c mklink "$1" "$(cygpath --windows --absolute "$2")" "$(cygpath --windows --absolute "$3")"
    else
        cmd /c mklink "$(cygpath --windows --absolute "$1")" "$(cygpath --windows --absolute "$2")"
    fi

}

Do note you need administrator permissions (for Cygwin) to run the above without problems.

Note that I am unaware whether there's any difference between symlinking to an absolute path versus symlinking to a relative path using CMD's mklink. On Linux, those 2 have different behaviours if you ever decide to move the symlink or move the target file, or move both.

CMCDragonkai
  • 6,222
  • 12
  • 56
  • 98
  • Nice alternative :-) Please provide Windows versions (and potentuially Cygwin/MinGW) on which you have tested your script to help other SO readers. Thanks ;-) – oHo Mar 24 '16 at 17:32
  • 3
    The `cygutils-extra` package includes a `winln` command which provides an `ln`-like syntax to create Windows native links. – Gene Pavlovsky Apr 23 '16 at 20:32
  • Ah that tool is great. It even suggests: `editrights -a SeCreateSymbolicLinkPrivilege -a $YOUR_USER`. – CMCDragonkai Apr 24 '16 at 06:55
  • 2
    But it should be `editrights -u $USER -a SeCreateSymbolicLinkPrivilege` actually. – CMCDragonkai Apr 24 '16 at 07:01
  • Didn't suggest it to me since I'm working as an administrator. – Gene Pavlovsky Apr 24 '16 at 10:48
  • Great tip for running mklink from cygwin (cmd /c mklink), thanks! – nexayq Nov 06 '20 at 12:24
  • @CMCDragonkai On Windows 10, enable _Developer Mode_ in _Developer Settings_ to be able to creative native NTFS symlinks in a non-elevated shell. Reference: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ – Gene Pavlovsky Jun 29 '22 at 13:27
0

I guess the easiest way is to

  1. grant SeCreateSymbolicLinkPrivilege from Local Group Policy editor (gpedit.msc, on path by default, non-home versions)

  2. create script named ln on path (batch or bash), implementation similar to above described shell function

  3. profit

oHo
  • 51,447
  • 27
  • 165
  • 200
Ate Somebits
  • 287
  • 1
  • 18
-5

You were probably looking for a way to get to another destination in catalogue tree using MSYS. There is a way. You should create a shell script ("*.sh" file) which contains line:

cd "/drive_letter/SubCatalogue/SubFolder/..." 
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • Hi FreeCodeRide. Thanks for your idea but I am not sure to understand. Please provide an example. For instance, you may create a target file, then a file linked to this target file... Cheers ;) – oHo Apr 14 '14 at 08:01