Better answer
Turns out with cygpath -F we can query a number of special "folder IDs". The following outputs the IDs along with the values for your system.
for ((id=0;id<=64;id++))
do
F=$(cygpath -amF $id 2> /dev/null)
[[ -n "$F" ]] && echo "$id = $F"
done
As a one-liner:
for ((id=0;id<=64;id++)); do F=$(cygpath -amF $id 2> /dev/null); [[ -n "$F" ]] && echo "$id = $F"; done
Meanwhile I checked in the code. The function get_special_folder() in cygpath.cc uses SHGetSpecialFolderLocation() and subsequently SHGetPathFromIDListW, so the value 42 (hexadecimal 0x2a) corresponds to CSIDL_PROGRAM_FILESX86 and so we can rely on this as long as Windows upholds its API contracts.
IMPORTANT: The "mixed representation" (cygpath -m) -- essentially Windows paths with forward slashes instead of backslashes -- appears to be more robust and portable across Cygwin flavors, including MSYS2!
Original answer
Here's a solution that works with Bash from Git for Windows and from Cygwin alike (should work with MinGW, too):
PF86="$(cygpath -u "$(env|tr -d '\r'|gawk -F= '$1 == "ProgramFiles(x86)" {print $2}')")"
The rest is making use of the populated environment variable. It is advisable to check if the output comes back empty and act accordingly, though. Example:
PF86="$(cygpath -u "$(env|tr -d '\r'|gawk -F= '$1 == "ProgramFiles(x86)" {print $2}')")"
[[ -n "$PF86" ]] || { echo "\${ProgramFiles(x86)} not set"; exit 1; }
Note: gawk can usually be substituted by awk. Depends on the exact details of your AWK script, but this one is so trivial, it should work in most if not all AWK flavors.
What does it do?
env lists environment variables as key=value pairs, one per line
tr -d '\r' deletes any carriage return from the stdin and writes the result to stdout
gawk -F= '$1 == "ProgramFiles(x86)" {print $2}')" uses = as field separator and matches for ProgramFiles(x86) in the first field. When matched, it prints field 2 (the value).
- the output from all the above steps is then used as input to
cygpath -u, converting the path from Windows to Unix representation
Please be aware that there is a very very subtle difference which causes the \r (carriage return) to remain part of the value for output captured from Windows programs. For the above the tr -d '\r' may not be strictly necessary, but I'd rather be safe than sorry.
Disclaimer: while this may not qualify as "pretty" in the stricter sense, it has turned out to be a very robust solution to the problem at hand. I have used it in numerous scripts, also professionally. One application I had was to use vswhere.exe, whose well-known path is based in this subfolder. Also vswhere was one of the cases where the tr -d '\r' workaround originated.
NB: I did not change the original answer above, but would strongly recommend the "mixed representation" (cygpath -m) as opposed "universal Unix representation" (I made that up; cygpath -U)!