env and PATH

Federico Kircheis federico@kircheis.it
Sat Jan 4 18:22:52 GMT 2025


On 04/01/2025 02.41, Andrey Repin wrote:
> Greetings, Federico Kircheis!
> 
>> Hello to everyone,
> 
> 
>> I've noticed that env seems to handle the environment variable PATH in a particular way
> 
> 
>> -----
>   >> cd /d;
>   >> env -i PATH='C:\Windows;C:\Windows\system32;' /c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
>> # in the powershell instance
>> echo $env:PATH
>> C;D:\Windows;C;D:\Windows\system32;
>> ----
> 
> Fully expected behavior. `env` expects POSIX semantics and parsed your
> command according to that.
> The results are, as I said, expected, although not by you.
What do you mean by POSIX semantic?
On my Linux system, PATH is used unmodified by subprocesses, not 
transformed.
This is (IMHO) the expected semantic.

I am not aware of any rule in POSIX that requires or recommends some 
transformations for environment variables, in that sense, any 
transformation is "unexpected" or an extension to the standard.

It completely makes sense to convert cygwin paths to windows path when 
invoking windows programs, but it is not my case.
Hence why I searched for an option, even an explicit one, to tell cygwin 
not to modify the parameters, but use them as-is.

>>   From this and other examples it seems that env uses for PATH  as
>> separator, then preprends the current drive to all paths that begin with '\'
>> (thus all of them), and ";" is treated as part of the path
> 
> Exactly.
> 
>> I would like to use the PATH as-is in the invoked program, just like it is done for other variables, for example
> 
>> ----
>> cd /d
>> env -i OPATH='C:\Windows;C:\Windows\system32;'
>> /c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
>> # in the powershell instance
>> echo $env:OPATH
>> C:\Windows;C:\Windows\system32;
>> ----
> 
>> in this case OPATH is forwarded as-is to powershell.exe.
> 
>> I understand that PATH is special, that for cygwin processes some transformation might be necessary.
> 
> It is, but in a way you suppose.
> 
>> But is there any way to achieve what I'm trying?
> 
> Yes. Pass the POSIX paths in $PATH, they will be converted to Windows ones
> when invoking a Windows process.
> Also, I strongly suggest using /proc/cygdrive/ tree in such case, especially
> when you make scripts for somebody else.

I was not aware of /proc/cygdrive/, thank you for the hint, although I 
am not sure how it helps.

>> I search if there is maybe a separation option for telling env to use PATH as-is, but could not find none.
> 
> There's no need or reason to do it.
> 
> In your case, what you wanted to achieve could be written as
> 
>>> env -i "PATH=$(cygpath -UW):$(cygpath -US):$PATH" pwsh

The reason is I already have a variable containing the path I should use 
as PATH, and it is the windows expected format.
I need to convert it to a cygwin path, so that env translates it back again.
It is doable, but sounds completely unnecessary.

Also it comes at a particular cost at runtime.
I want to start the subshell as fast as possible.
Iterating and invoking an external program (cygpath) for every path 
takes some time.

> (The "%SystemRoot%" is NOT NECESSARILY 'C:\Windows', though you CAN use
> "%SystemRoot%\System32" with confidence, once you acquired the former.)
> (Also, why the *** you are using v1.0? Get v7 already, save yourself the
> tragedy.)

Because the executable I invoked is the one installed on all Windows 
versions since Windows 7 (or maybe even Vista?).
Also the actual version is not 1.0, but something like 5.something (if I 
remember correctly)

v7 is AFAIK a different product, but most importantly it needs to be 
installed separately, and would not change the issue I have.


More information about the Cygwin mailing list