How to import any Linux command into your Windows 10 environment

At NeoSmart Technologies, we’re huge fans of the new Windows Subsystem for Linux,1 and have spent a lot of time trying to make the transition between the native Win32 subsystem and the Linux/WSL subsystem as seamless as possible.

For those of you that haven’t already seen it, we recommend reading our previous article Meet $, your new best friend for WSL for an introduction to WSL and $, our nifty helper utility that lets you directly run Linux commands in your Windows workflow. In brief, we developed $ (also known – though less affectionately – as RunInBash) to make it possible to run Linux utilities directly from within a Windows workflow, complete with arguments, stdinstdout, and stderr redirection, and more.

While $ makes it dead simple to run any Linux command by prefixing it with — yup, you guessed it — $, sometimes even that isn’t easy enough. For example, a lot of the developers at NeoSmart don’t use bash as their primary shell;2 so having to run another shell, say fish, by keying in +R then having to type in $ fish, while still a distinct improvement over bash -c fish, just didn’t cut it. And it’s not just a shell – there are a lot of “stand alone” command line utilities that developers rely on enough to launch directly without first entering a shell, such as ssh or nvim.

The ultimate solution we’ve landed on is a simple bash batch script that you can copy locally as many times as you like to launch any Linux tools you desire – without ever writing or changing a line of code.

Let’s jump straight into the batch file and then we’ll talk about how it works:

@echo off

set cmd=%~n0
$ %cmd% %*

Disappointed? Why, were you expecting more? That’s really all there is to it. The batch file above, when copied to a file called, let’s say, ssh.bat will run ssh under WSL, forwarding any arguments you pass to it along. All you have to do is put it in your PATH somewhere!

So how does it work? First, the batch file gets its own name via the %~n0 magic syntax.3 This gives us the file name without the directory component, so in this case, ssh – which will be taken as the name of the command to run on the Linux side of things.

The rest of the magic is all thanks to $, which takes care of escaping arguments and passing them to bash.exe in such a way that you can keep your sanity instead of pulling out your hair trying to figure out how to double-escape an ' in an argument enclosed in " when your command contains spaces and you need to pass it in to bash -c enclosed in another… forget it. That’s what $ is there for.

Have another Linux tool you use often? Just copy your ssh.bat over to tool.bat and you’ll be on your merry way. If you want to get all fancy, you can even create a symlink instead, and then if you ever want to make some changes to this batch file (though hopefully you’ll never need to) you’ll only need to change one and the rest will automatically follow suit. It really couldn’t get any easier than this.

If you don’t already have $ installed, you can either download it here or install it with chocolatey via choco install RunInBash.

  1. Yes, we refuse to call it by its ungodly “Bash on Ubuntu on Windows” moniker 

  2. And, honestly, who can blame them? Have you seen the syntax bash uses to access and escape elements of an array? 

  3. Yes, batch is ugly… perhaps even uglier than bash. 

  • Similar Posts

    Craving more? Here are some posts a vector similarity search turns up as being relevant or similar from our catalog you might also enjoy.
    1. Meet $, your new best friend for WSL
    2. $ (RunInBash) is now on Chocolatey
    3. Vista Gets It: Symlinks at Last!
    4. Scripting in rust with self-interpreting source code
    5. Proper Shell Scripting on Windows Servers with Perl
  • 3 thoughts on “How to import any Linux command into your Windows 10 environment

    1. Since win10 now supports symlinks, why copy the script? Just do what bsuybox does and create symlinks with the command names.

    Leave a Reply

    Your email address will not be published. Required fields are marked *