Summary:
In the most recent (Sept. 2020) version of 64-bit cygwin, the symlinks in the /bin/ and /lib directories have puzzling features, and seem to differ from any of the various other documented symlinks. The questions are:
why are they hidden from CMD.EXE, but visible elsewhere, unlike
other symlink types
is it possible to create symlinks with identical features? if so, how?
TL;DR
See @matzeri's answer: the SYSTEM attribute is set on /bin/awk, making it invisible to CMD.EXE sessions.
The symlinks below /bin and /lib seem to be one of the two types of "default cygwin symlinks" described here:
The default symlinks created by Cygwin are either special reparse
points shared with WSL on Windows 10, or plain files containing a
magic cookie followed by the path to which the link points. The
reparse point is used on NTFS, the plain file on almost any other
filesystem.
see symbolic links
However, all of the symlinks below /bin have the SYSTEM attribute set, and most of the symlinks below /lib don't. I don't know how was I able to create a symlink with a magic cookie on NTFS.
Below is the long version of the question
There are multiple types of symlinks under cygwin. Other questions explain their history, describe their differences, and show how to create them, etc. For example:
Here's a discussion of some of the history and problems with symlinks on windows:
As described, there are shortcuts, junction points, and symlinks, all of which are visible from a CMD.EXE session, as demonstrated.
However, under my 64-bit cygwin installation, there is another type that I can't find any explanation for. A number of them appear below /bin, /lib, and perhaps other places. The main characteristic that distinguishes them from the other 3 is that they aren't visible from a CMD.EXE session.
Here's one example:
If I attempt to list 'awk' via CMD.EXE from the /bin directory, the file seems to not exist:
$ cd /bin
$ cmd.exe /c dir awk
Volume in drive C is opt
Volume Serial Number is D0C8-EA58
Directory of C:\cygwin64\bin
File Not Found
Here's what it looks to to ls:
$ ls -l awk
lrwxrwxrwx 1 philwalk None 8 May 14 12:26 awk -> gawk.exe
But most symlinks, in my experience, ARE visible from a CMD.EXE session. Let's create a symlink for testing:
$ CYGWIN=winsymlinks:nativestrict # make sure we don't create an old-style symlink
$ ln -s `which ls.exe` ls-link
$ cmd.exe /c dir ls-link
Volume in drive C is opt
Volume Serial Number is D0C8-EA58
Directory of C:\opt\ue
2020-09-03 13:12 ls-link [C:\cygwin64\bin\ls.exe]
1 File(s) 0 bytes
0 Dir(s) 295,290,556,416 bytes free
This shows that CMD.EXE can see this type of symlink.
It appears that all symlinks can be dereferenced like this:
$ cygpath -w `which awk`
C:\cygwin64\bin\gawk.exe
So can a windows-based program dereference them? Can it see them at all? Because they aren't visible to CMD.EXE, I would have guessed that they aren't visible to any other windows (i.e., non-cygwin) program.
Here's a scala script, deref.sc, that will test these questions:
#!/usr/bin/env scala
import java.nio.file._
for( posixPath
val cyg = cygpath(posixPath)
val windows = Paths.get(posixPath)
val exists = Files.exists(windows)
printf("file path [%s]\n",posixPath )
printf("cygpath [%s]\n",cyg)
printf("windows [%s]\n",windows)
if( exists ){
printf("exists [%s] # visible to jvm-based programs\n",exists)
} else {
printf("exists [%s] # NOT visible to jvm-based programs\n",exists)
}
val realpath = if( exists ){
if( Files.isSymbolicLink(windows) ){
Files.readSymbolicLink(windows)
} else {
windows.toRealPath()
}
}
printf("real windows [%s]\n",realpath)
printf("\n")
}
def cygpath(posixPath:String) = {
import scala.sys.process._
Seq("cygpath.exe","-m",posixPath).lazyLines_!.mkString("")
}
Here's the output from deref.sc as applied to /bin/awk and to ./ls-link.
(we have to pass the windows-visible version of /bin/awk)
$ deref.sc ls-link
cygpath [ls-link]
windows [.\ls-link]
exists [true] # visible to jvm-based programs
real windows [C:\cygwin64\bin\ls.exe]
$ cd /bin
$ deref.sc awk
file path [awk]
cygpath [C:/cygwin64/bin/gawk.exe]
windows [awk]
exists [true] # visible to jvm-based programs
real windows [C:\cygwin64\bin\awk]
So this shows that, although some windows programs (such as CMD.EXE) cannot see c:/cygwin64/bin/awk, others (such as jvm-based programs) can!
My original question was based on the mistaken assumption that windows programs are not able to see these new symlinks, and since that isn't correct, the residual question is:
What are these new symlinks, and how are they created? Are they really different, or is this perhaps a side-effect of permissions? Running CMD.EXE as administrator seems to make no difference.
I verified that c:/cygwin64/bin/awk is also visible from a WSL session, although that's not so surprising given that the jvm can see them.
UPDATE: it seems that, although /bin/awk is visible to our program, it isn't considered to be a symbolic link by java.nio.file.Files.isSymbolicLink(). Its contents consist of the string "!gawk.exe", so it seems to be an early cygwin implementation of symlinks, before windows provided native symlinks.
It's unremarkable except for being invisible from CMD.EXE.
解决方案
The reason why the links are not visible is due to their file Attribute
S = System are not visible in CMD by DOS/Windows design,
from CMD, sorry in German, we have:
$ cmd
Microsoft Windows [Version 10.0.19041.450]
(c) 2020 Microsoft Corporation. Alle Rechte vorbehalten.
D:\cygwin64\bin>attrib zipinfo
S D:\cygwin64\bin\zipinfo
D:\cygwin64\bin>dir zipinfo
Datenträger in Laufwerk D: ist DATA
Volumeseriennummer: D603-FB6E
Verzeichnis von D:\cygwin64\bin
Datei nicht gefunden
D:\cygwin64\bin>dir /A:S zipinfo
Datenträger in Laufwerk D: ist DATA
Volumeseriennummer: D603-FB6E
Verzeichnis von D:\cygwin64\bin
19.06.2018 22:17 16 zipinfo
1 Datei(en), 16 Bytes
0 Verzeichnis(se), 542.542.495.744 Bytes frei