Module which allows you to run bash commands and other Linux programs from the Windows Subsystem for Linux directly from PowerShell, with support for piping to and from PowerShell commands.
Ensure you are running a recent Windows 10 Insiders build (>14316), and set up the Subsystem for Linux.
Grab the necessary files by cloning this repo:
git clone https://github.com/jimmehc/PowerBash.git
And import the PowerBash module (PowerShell doesn't like function names like "apt-get", so pass the -DisableNameChecking
switch to avoid that warning message):
Import-Module PowerBash\PowerBash.psm1 -DisableNameChecking
PowerBash is also available via the PowerShell Gallery:
Install-Module PowerBash
Import-Module PowerBash -DisableNameChecking
PowerBash looks in locations in the Linux Subsystem's filesystem for programs, equivalent to the following $PATH
:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/gcc/x86_64-linux-gnu/4.8:/usr/games
This is currently hardcoded, although I plan on making it configurable in future.
Any existing commands available to the current PowerShell session, including EXEs in the PowerShell $env:PATH
, cmdlets, functions, and aliases, will not be overridden by Linux programs. If you would like to use a Linux program of the same name instead, remove all functions, cmdlets, and aliases from your session prior to importing the module. For EXEs, you can pass the names of the programs you want overriden to the module via -ArgumentList
when importing (comma separated).
For example, sort
is an alias for Sort-Object
in PowerShell, and the Win32 utility, sort.exe
, is normally on your $env:PATH
. To use the Linux sort
utility instead, first remove the PowerShell alias:
Remove-Item alias:sort -Force
And then import PowerBash, passing "sort"
to -ArgumentList
:
Import-Module PowerBash\PowerBash.psm1 -DisableNameChecking -ArgumentList "sort"
apt-get
is treated specially. Whenever [sudo] apt-get install ...
is run, PowerBash is reloaded, causing the newly installed program to be instantly available.
The function ConvertTo-LinuxPath
(alias lxp
) is provided, to allow easier conversion between Windows versions of paths and the Linux equivalents.
For convenience, I've added a PSReadLine key handler for Alt-L, which will change Windows paths to Linux paths in place in the console:
(Note: ConvertTo-LinuxPath
is a quick and dirty implementation. It probably doesn't handle all escaping properly.)
When imported, PowerBash locates available Linux programs, and adds a wrapper for each one. Each wrapper handles pipe input and other arguments, and launches something like bash.exe -c "$Program $Args < $PipeArgs"
. Note that this incurs the performance overhead of launching a new bash.exe
process for every command.
This bug (UserVoice page) currently makes it impossible to connect the bash.exe
process` stdin/stdout/stderr to anything other than the console, which means piping directly to and from it cannot be done. As a consequence, PowerBash is designed around avoiding any scenario where PowerShell will try to redirect the input or output streams.
Unfortunately, this requires the use of temporary files for communication between PowerShell and the Linux Subsystem, which hurts performance. In playing with it myself, I haven't found it noticeable, but YMMV.
It was also necessary to add some hacky command introspection, involving examining ASTs to determine whether or not PowerShell will redirect the output of bash.exe
somewhere other than the console, which allows interactive apps to function alongside those used in pipelines. While I think I've covered most common scenarios with this, I have no doubt that there are some ways in which this breaks. If you see Error: 0x80070057
after running a command, please open a bug.