- Working across Windows and Linux file systems
- File storage and performance across file systems
- View your current directory in Windows File Explorer
- Filename and directory case sensitivity
- Interoperability between Windows and Linux commands
- Run Linux tools from a Windows command line
- Mixing Linux and Windows commands
- Run Windows tools from Linux
- Share environment variables between Windows and WSL with WSLENV
- WSLENV flags
- Disable interoperability
- Integrate Linux Commands into Windows with PowerShell and the Windows Subsystem for Linux
- PowerShell Function Wrappers
- Default Parameters
- Argument Completion
- Conclusion
Working across Windows and Linux file systems
There are a number of considerations to keep in mind when working between Windows and Linux file systems. We have outlined a few of them for you in this guide, including some examples of interoperability support for mixing Windows and Linux-based commands.
File storage and performance across file systems
We recommend against working across operating systems with your files, unless you have a specific reason for doing so. For the fastest performance speed, store your files in the WSL file system if you are working in a Linux command line (Ubuntu, OpenSUSE, etc). If you’re working in a Windows command line (PowerShell, Command Prompt), store your files in the Windows file system.
For example, when storing your WSL project files:
- Use the Linux file system root directory: \\wsl$\Ubuntu-18.04\home\ \Project
- Not the Windows file system root directory: /mnt/c/Users/ /Project$ or C:\Users\ \Project
When you see /mnt/ in the file path of a WSL command line, it means that you are working from a mounted drive. So the Windows file system C:/ drive ( C:\Users\ \Project ) will look like this when mounted in a WSL command line: /mnt/c/Users/ /Project$ . It is possible to store your project files on a mounted drive, but your performance speed will improve if you store them directly on the \\wsl$ drive.
View your current directory in Windows File Explorer
You can view the directory where your files are stored by opening the Windows File Explorer from the command line, using:
Alternatively, you can also use the command: powershell.exe /c start . Be sure to add the period at the end of the command to open the current directory.
To view all of your available Linux distributions and their root file systems in Windows File explorer, in the address bar enter: \\wsl$
Filename and directory case sensitivity
Case sensitivity determines whether uppercase (FOO.txt) and lowercase (foo.txt) letters are handled as distinct (case-sensitive) or equivalent (case-insensitive) in a file name or directory. Windows and Linux file systems handle case sensitivity in different ways — Windows is case-insenstive and Linux is case-sensitive. Learn more about how to adjust case sensitivity, particularly when mounting disks with WSL, in the Adjust case sensitivity how-to article.
Interoperability between Windows and Linux commands
Windows and Linux tools and commands can be used interchangeably with WSL.
- Run Windows tools (ie. notepad.exe) from a Linux command line (ie. Ubuntu).
- Run Linux tools (ie. grep) from a Windows command line (ie. PowerShell).
- Share environment variables between Linux and Windows. (Build 17063+)
Run Linux tools from a Windows command line
Run Linux binaries from the Windows Command Prompt (CMD) or PowerShell using wsl (or wsl.exe ).
Binaries invoked in this way:
- Use the same working directory as the current CMD or PowerShell prompt.
- Run as the WSL default user.
- Have the same Windows administrative rights as the calling process and terminal.
The Linux command following wsl (or wsl.exe ) is handled like any command run in WSL. Things such as sudo, piping, and file redirection work.
Example using sudo to update your default Linux distribution:
Your default Linux distribution user name will be listed after running this command and you will be asked for your password. After entering your password correctly, your distribution will download updates.
Mixing Linux and Windows commands
Here are a few examples of mixing Linux and Windows commands using PowerShell.
To use the Linux command ls -la to list files and the PowerShell command findstr to filter the results for words containing «git», combine the commands:
To use the PowerShell command dir to list files and the Linux command grep to filter the results for words containing «git», combine the commands:
To use the Linux command ls -la to list files and the PowerShell command > out.txt to print that list to a text file named «out.txt», combine the commands:
The commands passed into wsl.exe are forwarded to the WSL process without modification. File paths must be specified in the WSL format.
To use the Linux command ls -la to list files in the /proc/cpuinfo Linux file system path, using PowerShell:
To use the Linux command ls -la to list files in the C:\Program Files Windows file system path, using PowerShell:
Run Windows tools from Linux
WSL can run Windows tools directly from the WSL command line using [tool-name].exe . For example, notepad.exe .
Applications run this way have the following properties:
- Retain the working directory as the WSL command prompt (for the most part — exceptions are explained below).
- Have the same permission rights as the WSL process.
- Run as the active Windows user.
- Appear in the Windows Task Manager as if directly executed from the CMD prompt.
Windows executables run in WSL are handled similarly to native Linux executables — piping, redirects, and even backgrounding work as expected.
To run the Windows tool ipconfig.exe , use the Linux tool grep to filter the «IPv4» results, and use the Linux tool cut to remove the column fields, from a Linux distribution (for example, Ubuntu) enter:
Let’s try an example mixing Windows and Linux commands. Open your Linux distribution (ie. Ubuntu) and create a text file: touch foo.txt . Now use the Linux command ls -la to list the direct files and their creation details, plus the Windows PowerShell tool findstr.exe to filter the results so only your foo.txt file shows in the results:
Windows tools must include the file extension, match the file case, and be executable. Non-executables including batch scripts. CMD native commands like dir can be run with cmd.exe /C command.
For example, list the contents of your Windows files system C:\ directory, by entering:
Or use the ping command to send an echo request to the microsoft.com website:
Parameters are passed to the Windows binary unmodified. As an example, the following command will open C:\temp\foo.txt in notepad.exe :
This will also work:
Share environment variables between Windows and WSL with WSLENV
WSL and Windows share a special environment variable, WSLENV , created to bridge Windows and Linux distributions running on WSL.
Properties of WSLENV variable:
- It is shared; it exists in both Windows and WSL environments.
- It is a list of environment variables to share between Windows and WSL.
- It can format environment variables to work well in Windows and WSL.
- It can assist in the flow between WSL and Win32.
Prior to 17063, only Windows environment variable that WSL could access was PATH (so you could launch Win32 executables from under WSL). Starting in 17063, WSLENV begins being supported. WSLENV is case sensitive.
WSLENV flags
There are four flags available in WSLENV to influence how the environment variable is translated.
- /p — translates the path between WSL/Linux style paths and Win32 paths.
- /l — indicates the environment variable is a list of paths.
- /u — indicates that this environment variable should only be included when running WSL from Win32.
- /w — indicates that this environment variable should only be included when running Win32 from WSL.
Flags can be combined as needed.
Read more about WSLENV, including FAQs and examples of setting the value of WSLENV to a concatenation of other pre-defined environment vars, each suffixed with a slash followed by flags to specify how the value should be translated and passing variables with a script. This article also includes an example for setting up a dev environment with the Go programming language, configured to share a GOPATH between WSL and Win32.
Disable interoperability
Users may disable the ability to run Windows tools for a single WSL session by running the following command as root:
To re-enable Windows binaries, exit all WSL sessions and re-run bash.exe or run the following command as root:
Disabling interop will not persist between WSL sessions — interop will be enabled again when a new session is launched.
Источник
Integrate Linux Commands into Windows with PowerShell and the Windows Subsystem for Linux
September 26th, 2019
A common question Windows developers have is “why doesn’t Windows have yet?”. Whether longing for a powerful pager like less or wanting to use familiar commands like grep or sed , Windows developers desire easy access to these commands as part of their core workflow.
The Windows Subsystem for Linux (WSL) was a huge step forward here, enabling developers to call through to Linux commands from Windows by proxying them through wsl.exe (e.g. wsl ls ). While a significant improvement, the experience is lacking in several ways:
- Prefixing commands with wsl is tedious and unnatural
- Windows paths passed as arguments don’t often resolve due to backslashes being interpreted as escape characters rather than directory separators
- Windows paths passed as arguments don’t often resolve due to not being translated to the appropriate mount point within WSL
- Default parameters defined in WSL login profiles with aliases and environment variables aren’t honored
- Linux path completion is not supported
- Command completion is not supported
- Argument completion is not supported
The result of these shortcomings is that Linux commands feel like second-class citizens to Windows and are harder to use than they should be. For a command to feel like a native Windows command, we’ll need to address these issues.
PowerShell Function Wrappers
We can remove the need to prefix commands with wsl , handle the translation of Windows paths to WSL paths, and support command completion with PowerShell function wrappers. The basic requirements of the wrappers are:
- There should be one function wrapper per Linux command with the same name as the command
- The wrapper should recognize Windows paths passed as arguments and translate them to WSL paths
- The wrapper should invoke wsl with the corresponding Linux command, piping in any pipeline input and passing on any command line arguments passed to the function
Since this template can be applied to any command, we can abstract the definition of these wrappers and generate them dynamically from a list of commands to import.
The $command list defines the commands to import. Then we dynamically generate the function wrapper for each using the Invoke-Expression command (first removing any aliases that would conflict with the function).
The function loops through the command line arguments, identifies Windows paths using the Split-Path and Test-Path commands, then converts those paths to WSL paths. We run the paths through a helper function we’ll define later called Format-WslArgument that escapes special characters like spaces and parentheses that would otherwise be misinterpreted.
Finally, we pass on pipeline input and any command line arguments through to wsl .
With these function wrappers in place, we can now call our favorite Linux commands in a more natural way without having to prefix them with wsl or worry about how Windows paths are translated to WSL paths:
- man bash
- less -i $profile.CurrentUserAllHosts
- ls -Al C:\Windows\ | less
- grep -Ein error *.log
- tail -f *.log
A starter set of commands is shown here, but you can generate a wrapper for any Linux command simply by adding it to the list. If you add this code to your PowerShell profile, these commands will be available to you in every PowerShell session just like native commands!
Default Parameters
It is common in Linux to define aliases and/or environment variables within login profiles to set default parameters for commands you use frequently (e.g. alias ls=ls -AFh or export LESS=-i ). One of the drawbacks of proxying through a non-interactive shell via wsl.exe is that login profiles are not loaded, so these default parameters are not available (i.e. ls within WSL and wsl ls would behave differently with the alias defined above).
PowerShell provides $PSDefaultParameterValues , a standard mechanism to define default parameter values, but only for cmdlets and advanced functions. Turning our function wrappers into advanced functions is possible but introduces complications (e.g. PowerShell matches partial parameter names (like matching -a for -ArgumentList ) which will conflict with Linux commands that accept the partial names as arguments), and the syntax for defining default values would be less than ideal for this scenario (requiring the name of a parameter in the key for defining the default arguments as opposed to just the command name).
With a small change to our function wrappers, we can introduce a model similar to $PSDefaultParameterValues and enable default parameters for Linux commands!
By passing $WslDefaultParameterValues down into the command line we send through wsl.exe , you can now add statements like below to your PowerShell profile to configure default parameters!
Since this is modeled after $PSDefaultParameterValues , you can temporarily disable them easily by setting the «Disabled» key to $true . A separate hash table has the additional benefit of being able to disable $WslDefaultParameterValues separately from $PSDefaultParameterValues .
Argument Completion
PowerShell allows you to register argument completers with the Register-ArgumentCompleter command. Bash has powerful programmable completion facilities. WSL lets you call into bash from PowerShell. If we can register argument completers for our PowerShell function wrappers and call through to bash to generate the completions, we can get rich argument completion with the same fidelity as within bash itself!
The code is a bit dense without an understanding of some bash internals, but basically:
- We register the argument completer for all of our function wrappers by passing the $commands list to the -CommandName parameter of Register-ArgumentCompleter
- We map each command to the shell function bash uses to complete for it ( $F which is named after complete -F used to define completion specs in bash)
- We convert PowerShell’s $wordToComplete , $commandAst , and $cursorPosition arguments into the format expected by bash completion functions per the bash programmable completion spec
- We build a command line that we can pass to wsl.exe that ensures the completion environment is set up correctly, invokes the appropriate completion function, then outputs a string containing the completion results separated by new lines
- We then invoke wsl with the command line, split the output string on the new line separator, then generate CompletionResults for each, sorting them, and escaping characters like spaces and parentheses that would otherwise be misinterpreted
The end result of this is now our Linux command wrappers will use the exact same completion that bash uses! For example:
Each completion will provide values specific to the argument before it, reading in configuration data like known hosts from within WSL!
will cycle through options. will show all available options.
Additionally, since bash completion is now in charge, you can resolve Linux paths directly within PowerShell!
In cases where bash completion doesn’t return any results, PowerShell falls back to its default completion which will resolve Windows paths, effectively enabling you to resolve both Linux paths and Windows paths at will.
Conclusion
With PowerShell and WSL, we can integrate Linux commands into Windows just as if they were native applications. No need to hunt around for Win32 builds of Linux utilities or be forced to interrupt your workflow to drop into a Linux shell. Just install WSL, set up your PowerShell profile, and list the commands you want to import! The rich argument completion shown here of both command options and Linux and Windows file paths is an experience even native Windows commands don’t provide today.
The complete source code described above as well as additional guidance for incorporating it into your workflow is available at https://github.com/mikebattista/PowerShell-WSL-Interop.
Which Linux commands do you find most useful? What other parts of your developer workflow do you find lacking on Windows?
Let us know in the comments below or over on GitHub!
Источник