## What is WSL?
> [!Quote] From [Wikipedia: Windows Subsystem for Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux):
> **Windows Subsystem for Linux** (**WSL**) is a feature of Windows that allows developers to run a Linux environment without the need for a separate [virtual machine](https://en.wikipedia.org/wiki/Virtual_machine "Virtual machine") or [dual booting](https://en.wikipedia.org/wiki/Dual_booting "Dual booting")
> [!Quote] From [learn.microsoft.com](https://learn.microsoft.com/en-us/windows/wsl/install):
> Developers can access the power of both Windows and Linux at the same time on a Windows machine. The Windows Subsystem for Linux (WSL) lets developers install a Linux distribution (such as Ubuntu, OpenSUSE, Kali, Debian, Arch Linux, etc.) and use Linux applications, utilities, and Bash command-line tools directly on Windows, unmodified, without the overhead of a traditional virtual machine or dual-boot setup.
From the _Shell commands_ plugin's point-of-view, _Windows Subsystem for Linux (WSL)_ makes it easier to define cross-platform compliant shell commands in Obsidian, as a vault that is synced between multiple machines with different operating systems, can use a similar shell (e.g. [[Bash]]) on all operating systems. WSL is only available for Windows. Linux and macOS can use [[Bash]] (or some other Unix shell) natively without WSL-like system.
**From this point on, this page will only use the abbreviation _WSL_ to refer to _Windows Subsystem for Linux_.**
# Install WSL on Windows
As this documentation focuses on the usage of the _Shell commands_ plugin, WSL installation is out of the documentation's scope. If you don't have WSL installed already, you can follow the following installation guide: [Install Linux on Windows with WSL](https://learn.microsoft.com/en-us/windows/wsl/install).
> [!Info] WSL distro: Ubuntu
> This documentation assumes that WSL is installed with [Ubuntu](https://ubuntu.com/wsl) as it's <abbr title="distribution">distro</abbr>. That's also the default distro that `wsl --install` installs. However, this guide should work just perfectly for whatever distro. If you encounter problems with other distros, please start a discussion in the [_Debugging and testing_ discussion category on GitHub](https://github.com/Taitava/obsidian-shellcommands/discussions/categories/debugging-and-testing).
>
> <small>(Btw, if you have **multiple** distros installed, see [[#^multiple-distros|this tip for choosing which distro to use]] with your custom shell configuration.)</small>
# Configure a new _custom shell_: WSL
This section walks you through the configuring process step by step, just like [[Settings for custom shells]], but with the instructions adapted for WSL.
**To begin**, open up the settings panel in Obsidian by pressing the hotkey `Ctrl` + `,` . Navigate to _Shell commands_ -> _Environments_ -> _Custom shells_. Click the _New custom shell_ button. A modal pops up, where you can configure the custom shell's options as described in the below subchapters.
## Shell name and description
![[Settings-Custom-shell-WSL-Shell-name-and-description.png]]
The name and description are freely decidable, as they do not affect the custom shell's operation in any way.
_Shell name_: `Windows Subsystem for Linux (WSL)`
_Description_:
```
"WSL is a feature of Windows that allows developers to run a Linux environment without the need for a separate virtual machine or dual booting." (from: https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux)
This custom shell configuration allows you to execute Linux/Bash commands from Obsidian on Windows.
Install WSL: https://learn.microsoft.com/en-us/windows/wsl/install
```
## Executable binary file path
![[Settings-Custom-shell-WSL-Executable-binary-file-path.png]]
WSL's executable binary file path is: `C:\Windows\System32\wsl.exe` (at least on Windows 10).
## Shell arguments
![[Settings-Custom-shell-WSL-Shell-arguments.png]]
Use the following shell arguments:
```
--shell-type login
--
{{!shell_command_content}}
```
- `--shell-type login` tells WSL that startup scripts should be executed when invoking the shell (e.g. `~/.profile` and `~/.bashrc`). In practise, this ensures that the [[Additions to the PATH environment variable|$PATH environment variable]] will contain all directories needed to execute third party programs.
- The two dashes `--` are meant to be **included**, and should be on its own line, before `{{!shell_command_content}}`. The dashes indicate that no shell options will be defined **after** them, so everything **after** the dashes should be interpreted as executable commands.
Note that WSL does not use a `-c` switch before the `{{!shell_command_content}}` part, unlike many other shells do.
> [!Tip]- If you have multiple distros installed
> If you have multiple distros installed, you can specify what distro should be used by adding `-d DistroName` to the list of arguments:
> ```
> -d Ubuntu-22.04
> --shell-type login
> --
> {{!shell_command_content}}
> ```
> To get the names of all installed distros, you can execute `wsl -l` in a terminal.
> If you want to run certain shell commands in one distro, and others in another distro, you can create multiple custom shells, one for each distro. ^multiple-distros
![[Settings for custom shells#^about-shell-command-content]]
## Host operating system
![[Settings-Custom-shell-General-Host-operating-system-Windows-Quote-off.png]]
_Host operating system_ must be **Windows**, as WSL is run on Windows.
_Windows: Quote shell arguments_ must be **disabled**.
## Shell's operating system
![[Settings-Custom-shell-General-Shells-operating-system-Linux.png]]
_Shell's operating system_ must be **Linux**.
## Special characters escaping
![[Settings-Custom-shell-General-Special-characters-escaping-Unix.png]]
Select **Unix shell style with \\ as escape character**.
## Path translator
![[Settings-Custom-shell-WSL-Path-translator.png]]
As the [[#Shell's operating system]] differs from [[#Host operating system]], a _Path translator_ must be defined, so that Windows file paths get converted to a format that works in WSL. Use the following JavaScript function as the translator:
```javascript
const pathParts = absolutePath.match(/^([a-z]):\/(.+)$/ui);
const driveLetter = pathParts[1];
const trailingPath = pathParts[2];
return '/mnt/' + driveLetter.toLocaleLowerCase() + '/' + trailingPath;
```
> [!question]- Path translator code explained in detail
> Consider the following example path when interpreting the translator code: `C:\Obsidian vaults\My vault\MyNote.md`.
> 1. Before the translator code is called, the SC plugin has automatically replaced backslashes `\` with forward slashes `/` (because we selected `Linux` as the _Shell's operating system_ above).
> - So, `absolutePath` has a value of `C:/Obsidian vaults/My vault/MyNote.md`.
> 2. Split the path into two parts using a regular expression (regex):
> ```javascript
> const pathParts = absolutePath.match(/^([a-z]):\/(.+)$/ui);
> ```
> 1. `^` denotes a start of a string, as we want to pick up a letter that is the **first** character of the string.
> 2. `([a-z])` denotes that we want to pick up a drive letter that is any alphabet between `a` and `z`. (The letter can be upper or lower case, because a case-insensitive regex modifier `i` is used - see the point 2.5. below). Parenthesis `()` tell regex to store their content as the first part of the path.
> - Considering the example path, `C` is picked up as the drive letter.
> 3. A colon and a forward slash `:\/` are literal characters that are just assumed to be present after the drive letter. The colon `:` is not needed in the translated path, so it's simply discarded.
> - (The forward slash `/` is preceded with a backslash `\` to denote that it should be considered as a literal character, not as the end of the regex pattern).
> 4. `(.+)
denotes that we want to pick up all the rest of the characters as the second part of the path. The dot `.` denotes any character (a letter, a number, a whitespace or a punctuation character) and `+` tells to pick up at least one, but possibly multiple characters. The dollar `
denotes that all characters until the very end of the string should be picked up.
> - Considering the example path, `Obsidian vaults/My vault/MyNote.md` is picked up as the trailing part of the path.
> 5. Characters `ui` after the last forward slash `/` indicate regex _modifiers_:
> - `u` tells regex to support unicode characters, just in case any of them are present in `absolutePath`.
> - `i` tells regex to pick up also uppercase drive letters, even though the pattern only expresses lowercase letters `a-z`.
> 3. Assign the picked up parts to constants `driveLetter` and `trailingPath`.
> ```javascript
> const driveLetter = pathParts[1];
> const trailingPath = pathParts[2];
> ```
> - `driveLetter` becomes `C`.
> - `trailingPath` becomes `Obsidian vaults/My vault/MyNote.md`.
> 4. Add a prefix, concatenate the path parts together, and return the result.
> ```javascript
> return '/mnt/' + driveLetter.toLocaleLowerCase() + '/' + trailingPath;
> ```
> - `/mnt/` is used in WSL as a special directory via which Windows file system can be accessed.
> - `/mnt/` is followed by a Windows drive letter (which must be converted to lower case).
> - The rest of the path is presented after the drive letter, separated by a forward slash `/`.
> - The translator returns the result `/mnt/c/Obsidian vaults/My vault/MyNote.md`.
Test that the path translator works by clicking the _Test absolute path translation_ icon: ![[Translate-icon.png]]. It should provide three test paths:
![[Settings-Custom-shell-WSL-Path-translation-test.png]]
Your paths will be different, as you have your vault in a different directory, and differently named files. **Just make sure all the three paths start with `/mnt/`** .
![[Settings for custom shells#^what-file-system-paths-are-translated]]
## Wrapper for shell command
![[Settings-Custom-shell-General-Wrapper-for-shell-command-Empty.png]]
You can leave the wrapper field empty. A wrapper could be defined if you'd like to execute certain commands before and/or after the main command, but there's no explicit need for it.
![[Settings for custom shells#^about-shell-command-content]]
## Execute a command to test the shell
![[Settings-Custom-shell-WSL-Execute-command-to-test-shell.png]]
You can define e.g. the following test command:
```bash
echo "Hello $USER, current working directory is: $(pwd)"
```
Click the _Execute the test command using this shell_ icon button: ![[Execute-icon.png]]
Make sure that the outputted _current working directory_ is your Obsidian vault's path (assuming you have not changed the [[Working directory]] setting).
Example result for me:
![[Settings-Custom-shell-WSL-Execution-test.png]]
## Make shell commands use the newly created WSL shell
![[Settings for custom shells#Make shell commands use the newly created shell]]
# History
> [!page-edit-history]- Page edit history: 2023-04-02 ➔ 2023-11-26
> - [<small>2023-11-26</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/91a0808dd6e1ddc64db26d6931ff73f1cbe4a918): [[Windows Subsystem for Linux (WSL).md]]: Add `-shell-type login` argument.
> - [<small>2023-11-26</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/6306e0b87569083c9e6c1ceace8f4f4846001e23): [[Windows Subsystem for Linux (WSL).md]]: Explain path translator details.
> - [<small>2023-11-26</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/dfcbec7cdd993836578aeea96f002004ca33fb6b): [[Windows Subsystem for Linux (WSL).md]]: Mention that no `-c` switch is used with WSL.
> - [<small>2023-11-26</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/f38c1167c404a492729f9e692029aa73b2fc2585): [[Windows Subsystem for Linux (WSL).md]]: Add a tip about choosing a distro.
> - [<small>2023-04-16</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/79ac0bd858ee53b8b721ba44d5d980c2325f0f1f): [[Windows Subsystem for Linux (WSL).md]]: Use WSL specific screenshots.
> - [<small>2023-04-10</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/836d6a75e93c7664cf895a02722ec688f612f172): [[Windows Subsystem for Linux (WSL).md]]: Rename a heading.
> - [<small>2023-04-10</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/92811b9c999f3459792dd2ab6639f77b9477466b): [[Windows Subsystem for Linux (WSL).md]]: Add more info to [[#Wrapper for shell command]].
> - [<small>2023-04-10</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/e10d73ad0efbeb59eccdd175d3c7c8628630dd54): [[Windows Subsystem for Linux (WSL).md]]: Add more info to [[#Path translator]].
> - [<small>2023-04-10</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/47744de2b41b0ae2f44a8cbe83d4bcd0301bf3bc): [[Settings for custom shells.md]]: Add content.
> - [<small>2023-04-02</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commit/7bd74c26aac68d0051a128d58fa15f8f3d6f03f5): Custom shell example: Windows Subsystem for Linux (WSL)
>
> [<small>See this list of commits on GitHub</small>](https://github.com/Taitava/obsidian-shellcommands-documentation/commits/main/Environments/Custom%20shells/Windows%20Subsystem%20for%20Linux%20%28WSL%29.md).
> ^page-edit-history