Click here to Skip to main content
13,255,238 members (53,583 online)
Click here to Skip to main content
Add your own
alternative version

Stats

4.3K views
9 downloads
5 bookmarked
Posted 9 Nov 2017

Proper Bash scripting on Windows: Associate SH scripts to WSL (Windows 10) (enable drag-and-drop to .sh) (+other linux executables)

, 16 Nov 2017
Rate this:
Please Sign up or sign in to vote.
Guide to properly set up Windows 10 for Shell scripting

Introduction

It's finally out! After a long beta testing phase, Windows Subsystem for Linux (formerly known as Bash on Ubuntu on Windows) has finally reached its first stable release in Windows 10 version 1709, and it won't disappoint you: with the Microsoft Store integration and new distributions gradually being released, WSL seems to be reaching its true potential, as bugs get fixed and more users start to prefer it over a multi-boot system (but let's avoid starting a Windows vs Linux OS war, that's not what this article is about 😉).

As you probably already know (unless you came across this article by chance), WSL - by default- still doesn't allow you to associate an SH script (.sh files) to bash.exe or wsl.exe (or any other linux executable files like .out and .elf), nor dragging files and folder to a script to pass them as parameters. Moreover, you might be having a bad time creating/editing said scripts if you are a fresh-of-Windows Linux user.

But worry not, because the solution (for the first two issues) is quite simple: a Windows registry key!

SH/ELF file association and drag-over

If, again, you are a Windows newbie wondering what the fudge a registry key (or the Windows registry) is and you are not a lazy reader, you will find the answer to all your questions by clicking here, I'll just let you know you can install a key (or merge it, to use proper terminology) by simply double-clicking it; pretty convenient if you ask me.

So, if you just came here for the fix, the download is on top of the article: remember to download the latest version; that is unless you like bugs and missing features (who am I to judge you). After merging the registry key, just set bash.exe or wsl.exe as default program to open the .sh files (They are located in C:\Windows\System32)

The script also supports the following distro-specific executables: ubuntu.exeSLES-12.exe and openSUSE-42.exe.

The registry key will also enable dragging files over scripts/executables to use them as parameters, a right-click > run as admin option, comes with an optional right-click > edit with nano key, as well as an extra right-click into folder > open WSL here key and some extra Icon options for the associated files.

Please note that you can now also associate any kind of linux executable to WSL: that includes .out files created after compiling some code, ELF executables and other executable binary files. Since Linux OS, as opposed to Windows, does not require using an extension for such files, you could give them any extension, a still unused file extension (i propose .lxx) or just .elf would be fine.

Creating and editing .sh files

You could acknowledge this for the easy step, but you'd be mistaken... at least until you install a good text editing software. It is, indeed, common knowledge, that Windows' Notepad is THE SPAWN OF SATAN itself and you shall never use it UNDER ANY CIRCUMSTANCES.

Jokes aside, Windows Notepad is only designed to work with Windows line endings ("\r\n") and won't recognise Unix line endings ("\n"), but there are a lot of alternatives, like Notepad++, or my personal favourite, Programmer's Notepad.

Alternatively, the rar archive downloadable above will provide an optional key to add the edit (linux nano editor) option in the context menu (file right-click). Nano isn't the most practical editor, but it gets the job done.

Once installed, just create a new.txt file, rename the extension to .sh, open it with [NOT_NOTEPAD], find the file_properties/line_endings somewhere (ex: File>Properties in Programmer's Notepad) and change line endings to Unix ones (You don't need to worry for nano); You only need to do this for a new file.

How the SH association script works

We are going to work with the keys inside [HKEY_CLASSES_ROOT\Applications\bash.exe] and [HKEY_CLASSES_ROOT\Applications\wsl.exe].

First of all, let's enable drag-over for all files opened with bash.exe or wsl.exe by adding a DropHandler in "...\shellex\DropHandler" key; I won't go as far as creating a new drop handler, so i'll just use vbs files' drop handler:

{60254CA5-953B-11CF-8C96-00AA00B8708C}

The "...\shell\open\command" key of the Windows registry is able to - you guessed it- execute a command; for the open-with command this is, in most cases:

"PROGRAM_TO_OPEN_THE_FILE_WITH'S_PATH\program.exe" "%L" "%*"

The command will run everytime a file associated to program.exe is opened; %L is the path of the file we are opening, and %* are the paths of the dragged files we get thanks to the drop handler; this WON'T WORK for WSL.

We can, however, exploit this system: bash.exe and wsl.exe can both be called to silently execute a bash script: by using the -c option for the former, and by simply writing the commands afterwards for the latter. What we CAN do is, therefore, writing a small bash script that parses all the arguments from Windows paths to Unix paths, and then run the actual .sh script / linux executable file.

#Gets all file paths without expansion/substitution
read -r -d '' path_param <<'EOF'
PARAMETERS_PATHS_HERE
EOF
read -r -d '' path_exec <<'EOF'
SCRIPT_PATH_HERE
EOF

#Parses all dragged files' paths from Windows paths to unix paths
path_param=$(echo $path_param | tr -d '"' | sed 's/[[:space:]]\([A-Z]:\)/\n\1/g' | sed 's/[A-Z]:/\/mnt\/\L&/g' | tr '\\' '\/'\');
mapfile -t path_param <<< "$path_param";
path_param=("${path_param[@]//:}");

#Same, but with the .sh script path
path_exec=$(echo $path_exec | sed 's/[[:space:]]\([A-Z]:\)/\n\1/g' | sed 's/[A-Z]:/\/mnt\/\L&/g' | tr '\\' '\/'\'); 
path_exec="${path_exec//:}";

#Sets working directory to the folder where the script is located
cd "${path_exec%\/*}";

#Executes script with or without parameters
if [[ ${path_param[@]} == "" ]];
    then "$path_exec";
    else "$path_exec" "${path_param[@]/#${path_exec%\/*}\/}";
fi;

#Leaves WSL console open after the .sh script finishes executing (optional)
cd ~; bash;

To fit all this code inside a single Windows registry key we must replace all % characters with %% and all newlines with ;. That with the exception of the newline characters between heredoc commands (initial read commands), where we'll use a linefeed character, which i will represent with the poop emoji for convenience (💩).

Let's thus turn the (relatively) beautiful code you see above into the following abominations for bash.exe and wsl.exe command keys (REG_EXPAND_SZ types):

"%SYSTEMROOT%\System32\bash.exe" -c printf\ \"\"💩read -r -d '' path_param <<'EOF'💩%*💩EOF💩read -r -d '' path_exec <<'EOF'💩%L💩EOF💩path_param=$(echo $path_param | tr -d '"' | sed 's/[[:space:]]\([A-Z]:\)/\n\1/g' | sed 's/[A-Z]:/\/mnt\/\L&/g' | tr '\\' '\/'\'); mapfile -t path_param <<< "$path_param"; path_param=("${path_param[@]//:}"); path_exec=$(echo $path_exec | sed 's/[[:space:]]\([A-Z]:\)/\n\1/g' | sed 's/[A-Z]:/\/mnt\/\L&/g' | tr '\\' '\/'\'); path_exec="${path_exec//:}"; cd "${path_exec%%\/*}"; if [[ ${path_param[@]} == "" ]]; then "$path_exec"; else "$path_exec" "${path_param[@]/#${path_exec%%\/*}\/}"; fi; cd ~; bash;
"%SYSTEMROOT%\System32\wsl.exe" read -r -d '' path_param <<'EOF'💩%*💩EOF💩read -r -d '' path_exec <<'EOF'💩%L💩EOF💩path_param=$(echo $path_param | tr -d '"' | sed 's/[[:space:]]\([A-Z]:\)/\n\1/g' | sed 's/[A-Z]:/\/mnt\/\L&/g' | tr '\\' '\/'\'); mapfile -t path_param <<< "$path_param"; path_param=("${path_param[@]//:}"); path_exec=$(echo $path_exec | sed 's/[[:space:]]\([A-Z]:\)/\n\1/g' | sed 's/[A-Z]:/\/mnt\/\L&/g' | tr '\\' '\/'\'); path_exec="${path_exec//:}"; cd "${path_exec%%\/*}"; if [[ ${path_param[@]} == "" ]]; then sudo "$path_exec"; else sudo "$path_exec" "${path_param[@]/#${path_exec%%\/*}\/}"; fi; cd ~; bash;

Welcome to the Dark Side of programming.

History

[08/11/2017] CodeProject first upload (script version 8)

[15/11/2017] Greatly improved parser script, switched to VBS DropHandler (script version 9)

[16/11/2017] Added distro-specific executable support, fixed open-here bugs (script version 10)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionSnippets Pin
Nelek12-Nov-17 8:07
protectorNelek12-Nov-17 8:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171114.1 | Last Updated 16 Nov 2017
Article Copyright 2017 by Alex the Green Apple
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid