Search code examples
bashpowershellpwd

Keep bash cwd the same directory as cwd of Powershell that spawned it


I have a Powershell session that creates bash session to run a script like so

C:\msys64\usr\bin\bash -lc './super_duper_script.sh

Where the super_duper_script.sh is in the cwd of Powershell session. The unfortunately when the bash session starts its cwd is '/home/username' not the cwd of the Powershell session.

Here's what I have managed so far:

C:\msys64\usr\bin\bash -lc "cygpath -u '$PWD'"

echos the cwd of the Powershell session. The problem now is that setting the cwd of the bash session is proving to be a challenge. Here's are just two of my failed attempts:

C:\msys64\usr\bin\bash -lc "env --chdir=(cygpath -u '$PWD')

C:\msys64\usr\bin\bash -lc "cd {cygpath -u '$PWD'}"

Setting the .bashrc is not an option, because this stuff is running in CI, besides various bash scripts can be invoked in different directories.


Solution

  • Because the working-directory information you want to convey belongs to the PowerShell session and is lost when it starts Bash, you need to capture it via PowerShell. The $PWD PowerShell variable provides it in the form of a Windows path, and apparently, in your Bash environment, the cygpath command will convert the Windows path into a corresponding path for your Bash session. Note in particular, then, that this ...

    C:\msys64\usr\bin\bash -lc "cygpath -u '$PWD'"
    

    ... relies on PowerShell to expand $PWD into the content of a Bash single-quoted string serving as an argument to a cygpath command executed by Bash. I imagine you already knew that.

    Here's are just two of my failed attempts:

    C:\msys64\usr\bin\bash -lc "env --chdir=(cygpath -u '$PWD')
    

    There are at least three issues with that:

    1. It is missing a closing double quote. This is probably just a typo in the question.

    2. It does not specify a command for env to run. Possibly this was accidentally truncated along with the closing double quote

    3. The (cygpath -u '$PWD') seems intended to be a Bash command substitution (where $PWD was already expanded by PowerShell), but it has the wrong syntax. The Bash syntax for command substitution is $(command ...) -- the same as PowerShell's syntax for the same thing, I think.

    It looks like what you want here is probably something more like this:

    C:\msys64\usr\bin\bash -lc "env --chdir=`$(cygpath -u '$PWD') bash ./super_duper_script.sh"
    

    The backtick (`) escapes the following $ from PowerShell, but since the overall string is double quoted, PowerShell will still do the needed expansion of $PWD.

    But that's needlessly complex. There is no need to get env involved when you can instead do this:

    C:\msys64\usr\bin\bash -lc "cd `$(cygpath -u '$PWD') && . super_duper_script.sh"
    

    That has Bash do the directory conversion via command substitution as before, then change to the directory designated by the result, and on success, it then has Bash read and execute the contents of the script directly (that is, without launching another shell).

    C:\msys64\usr\bin\bash -lc "cd {cygpath -u '$PWD'}"
    

    I'm not sure exactly what that one is trying to do. The { ... } are meaningful to both PS and Bash, but neither one attributes a meaning that makes that attempt sensible to me. Even if one did, there is no invocation of the script you ultimately want to run.