powershellcygwin

Powershell 5 and 7 processes double quotes in different way when running Cygwin


I need to run bash commands under Powershell using Cygwin's bash.

I faced the issue that Powershell 5 and 7 processes double quotes in different way.

I'd like to have bash script working in both. Can I set up both Powershell to make them processing quotes in the same way? Or another way to have export MYKEY="MYVALUE" with double quotes in Cygwin?

Powershell 5:

PS D:\work> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      22621  3958

PS D:\work> C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key="$value";'
export MYKEY=MYVALUE

PS D:\work> C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key=\"$value\";'
export MYKEY=MYVALUE

PS D:\work> C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key=\\\"$value\\\";'
export MYKEY="MYVALUE"

Powershell 7:

PS D:\work> $PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      4

PS D:\work> C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key="$value";'
export MYKEY=MYVALUE

PS D:\work> C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key=\"$value\";'
export MYKEY="MYVALUE"

PS D:\work> C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key=\\\"$value\\\";'
export MYKEY=\"MYVALUE\"

Solution

  • It is PowerShell (Core) 7's behavior that is correct, specifically in v7.3+, which corrected a long-standing bug that still affects Windows PowerShell - see this answer for details.

    You can instruct PowerShell 7.3+ to exhibit the old, broken behavior via the $PSNativeCommandArgumentPassing preference variable, by setting it to 'Legacy':

    Therefore, the following snippet makes the bash.exe call exhibit the same behavior in both PowerShell editions:

    if ($IsCoreCLR) { $PSNativeCommandArgumentPassing = 'Legacy' }
    C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key=\\\"$value\\\";'
    
    # Alternatively, with a specific version check, which also avoids
    # strict-mode problems, given that the $IsCoreCLR variable isn't defined
    # in Windows PowerShell:
    if ($PSVersionTable.PSVersion -ge '7.3') { $PSNativeCommandArgumentPassing = 'Legacy' }
    C:\cygwin64\bin\bash.exe -l -c 'key=MYKEY; value=MYVALUE; echo export $key=\\\"$value\\\";'
    

    Note: