The robust and efficient way to execute your shebang-line-based shell script from Windows is via wsl.exe -e
wsl -e ./simple_script.sh # !! ./ is required
Note:
Without ./
to explicitly indicate that the executable is located in the current directory, the command would fail quietly (only executables located in directories listed in the PATH
environment variable can be invoked by name only).
-e
bypasses involvement of a shell on the Linux side, and instead lets a Linux system function interpret the shebang-line-based plain-text file, which automatically honors the specified interpreter.
- Perhaps surprisingly, WSL considers all files located in the Windows file-system, including plain-text ones, to have the executable bit set, which you can easily verify with
wsl -e ls -l ./simple_script.sh
As for what you tried:
$simple_script = Get-Content ./simple_script.sh
wsl bash -c $simple_script
The primary problem is that Get-Content
by default returns an array of lines, and attempting to use that array as an argument to an external program such as wsl
causes the array's elements to be passed as individual arguments.
The immediate fix is to use the -Raw
switch, which makes Get-Content
return the file content as a single, multi-line string.
However, due to a highly unfortunate, long-standing bug, PowerShell - up to v7.2.x - requires manual \
-escaping of embedded "
characters in arguments passed to external programs.
Therefore:
# Using -Raw, read the file in full, as a single, multi-line string.
$simple_script = Get-Content -Raw ./simple_script.sh
# !! The \-escaping is needed up to PowerShell 7.2.x
wsl bash -c ($simple_script -replace '"', '\"')
Note that while it is tempting to try to bypass the need to escape by providing the script text via the pipeline (stdin), this does not work as expected, as of PowerShell 7.3.3:
# !! Tempting, but does NOT work.
Get-Content -Raw ./simple_script.sh | wsl -e bash
The reason this doesn't work is that PowerShell invariably appends a Windows-format newline (CRLF) to what is being sent to external programs via the pipeline, which Bash doesn't recognize.