DrvFs location of %UserProfile% - bash

From within the Windows Subsystem for Linux, how can I get the DrvFs path that points to what would be %UserProfile% inside the Windows personality? I've seen Access Windows Environment Variables from within Bash in WSL. It seems rather involved for getting one environment variable, and requires hard-coding something from within %UserProfile% anyway ($LXSS_ROOT).

This seems to work:
win_userprofile="$(cmd.exe /c "<nul set /p=%UserProfile%" 2>/dev/null)"
win_userprofile_drive="${win_userprofile%%:*}:"
userprofile_mount="$(findmnt --noheadings --first-only --output TARGET "$win_userprofile_drive")"
win_userprofile_dir="${win_userprofile#*:}"
userprofile="${userprofile_mount}${win_userprofile_dir//\\//}"
Thanks to Craig Loewen at Microsoft for getting me started.

Fortunately since Windows 10 build 17063 (included in Windows 10 1803) there is a more straightforward way of sharing environment variables between Windows and WSL (WSLENV).
To make %USERPROFILE% accessible in WSL you list the variable in the WSLENV variable. If you are not using WSLENV yet then just run this once in Windows:
setx WSLENV USERPROFILE/up
This will cause %USERPROFILE% from Windows to be accessible as $USERPROFILE in WSL shell with Windows path converted to the Unix format. If you do not want to convert the path, just omit the p:
setx WSLENV USERPROFILE/u
More details:
https://learn.microsoft.com/en-us/windows/wsl/interop#share-environment-variables-between-windows-and-wsl
https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/
I use the variable in my cdw function (cd to Windows path). I define it in ~/.bash_aliases which is executed automatically in Ubuntu:
#!/bin/bash
cdw () {
if test "$#" -eq 0 ; then
cd "$USERPROFILE"
elif test "$1" = - ; then
cd "$1"
else
cd -- "$(wslpath "$#")"
fi
}

Related

How do you pass an environment variable from WSL into windows executable

From a Windows Subsystem for Linux (v1) Alpine bash terminal, I would like to set an environment variable that get's passed into a windows executable. Is there any way to do this?
example of what I was hoping would print "Hello, World!":
windows-10:~# export X=World
windows-10:~# cmd.exe /c 'echo Hello, %X%!'
Hello, %X%!
See answer from Philipe below.
Here is a copy of the pertinent info from https://learn.microsoft.com/en-us/windows/wsl/interop
Share environment variables between Windows and WSL
Available in Windows Insider builds 17063 and later.
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, WSL and Windows share WSLENV, a special environment variable created to bridge Windows and Linux distros running on WSL.
Properties of WSLENV:
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.
There are four flags available in WSLENV to influence how that environment variable is translated.
WSLENV flags:
/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.
Can you try this ?
~$ export X=World
~$ export WSLENV=X/w
~$ cmd.exe /c 'echo Hello, %X%!'
Hello, World!

Why `${PATH//\/\/wsl\$+([^:]):/}` executes very slowly

When I run bash.exe in Git for Windows from WSL bash, I want to pass PATH from WSL to Win32, and filter out //wsl$/*** items in Win32 bash scripts. So I tried echo ${PATH//\/\/wsl\$+([^:]):/} but it takes several seconds to run.
My Win 10 is v1903 x64, WSL bash is from Ubuntu, and Git for Windows is v2.22.0.windows.1 . My CPU is Intel E3-1230 v5 .
The below is how I get a $PATH including //wsl$ :
open WSL bash, modify $PATH and export it
run WSLENV=PATH/l start2.exe /d/Git/usr/bin/bash.exe to get a new console window of bash.exe in Git for Windows
start2.exe is a tool of mine just to run exe in another console
echo $PATH shows something like /mingw64/bin:/usr/bin:/d/Program Files/nodejs://wsl$/Ubuntu/mingw64/bin:...
But in my computer, access to //wsl$/Ubuntu/*** is denied after once system upgrading. So I need to remove these //wsl$/* items from $PATH, otherwise the bash.exe seems to run slowly.
I tried export PATH="$(echo "$PATH" | sed -r 's|//wsl[^:]+:||g')" and it worked, but I want to use built-in commands to do so (the code below has been edited):
shopt -s extglob
if [[ $PATH == *//wsl\$* ]]; then
PATH=${PATH//\/\/wsl\$+([^:]):/} # this line takes seconds
fi
I expect it runs quickly, but the code above is very very slow.
Added:
The main problem is my PATH is dynamic in WSL bash, and can even be changed by myself, so I can not pre-set a constant PATH for Git for Windows's bash.

How to start Atom or VSCode natively installed on Windows from within WSL (Ubuntu)?

I have installed Atom editor natively on Windows 10 by downloading an running the installer. Now I start WSL Ubuntu distro and want to start Atom (atom-editor) from there with the command atom . or VSCode (visual-studio-code) with the command code .
Atom starts, but not in the directory where the command was executed, instead it shows files from C:\\Windows. Moreover Ubuntu WSL terminal shows following error message:
atom .
grep: /etc/wsl.conf: No such file or directory
"\\wsl$\Ubuntu-18.04\home\wlad\projects\udemy\flask-bootcamp\Flask-Bootcamp-master"
CMD.EXE wurde mit dem oben angegebenen Pfad als aktuellem Verzeichnis gestartet.
UNC-Pfade werden nicht unterstützt.
Stattdessen wird das Windows-Verzeichnis als aktuelles Verzeichnis gesetzt.
Sorry it's German localized but it says something like UNC-paths are not supported
(haven't tested VSCode yet)
So how can I use Atom or VSCode editor installed on Windows 10 from within WSL?
** UPDATE **
As of today (April 2020) there is a much better way to use VSCode on Windows w/ WSL, VirtualMachines (VM) and even Containers. Check out remote-development plugin for VSCode.
I created a short script to handle the three atom commands I use most (I use Ubuntu with WSL):
atom
atom .
atom RELATIVE_PATH_FILE
This script is not optimized, and I'm sure many people will find edge cases, but it gets the job done for me. To use it, simply placed it in ~/.local/bin/atom and make it executable by running chmod +x ~/.local/bin/atom. You may need to restart your shell for ~/.local/bin to be added to your path. In order to simplify things a bit, I mapped the WSL network drive for my ubuntu installation to U:, so you'll either want to do the same or modify the script accordingly on line 9.
#!/bin/bash
if [ -z $1 ]; then
pushd /mnt/c > /dev/null
/mnt/c/Windows/System32/cmd.exe /c "atom"
else
[[ $1 = "." ]] && path=$(pwd) || path=$(realpath $1)
winPath=$(echo "U:$path" | sed -e 's/\//\\/g')
pushd /mnt/c > /dev/null
/mnt/c/Windows/System32/cmd.exe /c "atom $winPath"
fi
popd > /dev/null
The script performs a few simple steps. First, if there is no command line argument, it simply calls atom using cmd.exe without arguments. If the command line argument is ., it gets the path to the current directory, otherwise, it gets the absolute path to the given file using realpath. The path is converted from POSIX to Windows format using sed before calling atom using cmd.exe as before, but with the path argument.
The pushd and popd commands are just there to get rid of the annoying warning message about UNC paths not being supported:
...
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory
In the "Known issues" section of the blog post #Wlad mentioned, there states
Accessing Linux files is treated the same as accessing a network resource, and any rules for accessing network resources will still apply e.g: When using CMD, cd \\wsl$\Ubuntu\home will not work (as CMD does not support UNC paths as current directories), however copy \\wsl$\Ubuntu\home\somefile.txt C:\dev\ will work
So as Atom may use cmd.exe to launch itself from the command line (maybe some batch file), and given the fact that cmd.exe cannot open network resources as current directory (which WSL directory is treated as), there came the failure as you attempted to launch Atom from WSL shell.
Actually, in VS Code there is a better solution to launch VS Code directly from the WSL shell: VS Code Remote.
You can take the following steps to enable VS Code to be directly launched from WSL shell:
Install the extension Remote - WSL to VS Code on the Windows side;
Then when you type code . in your WSL shell, VS Code Remote Server will be automatically installed, and VS Code will soon launch.
By using VS Code Remote, you can not only open the directory in VS Code, but can also be benefited in many other aspects: for example, you can use the WSL shell as the integrated shell in VS Code and run programs in WSL directly from VS Code.
Here is the official doc for VS Code Remote - WSL.
The script in Eduardo's answer is a great approach, but didn't allow to open multiple directories/repos at once (e.g. atom terraform-modules terraform-repo), which I do often.
The following is my twist on it:
#!/bin/bash
winPathPrefix="U:"
function convertToWinPath() {
echo "${winPathPrefix}$(realpath ${1})" | sed -e 's/\//\\/g'
}
declare -a atomCmd=(/mnt/c/Windows/System32/cmd.exe /c "atom")
for path in "$#"; do
atomCmd+=($(convertToWinPath ${path}))
done
${atomCmd[#]} 2>/dev/null
That is entirely based on Eduardo's script and should allow a more general use case
Wanting to run Atom from WSL got me here but unfortunately the accepted answer does not mention atom and the other atom related workarounds don't work anymore.
In case someone googles the question and ends up here. Here's an actual workaround (It will break in new Atom updates).
Add the following path path in the windows enviroments: C:\Users\{username}\AppData\Local\atom\app-{version}\ (at the time of this post the version is 1.60.0 so app-1.60.0.
Use the path mentioned above as the default path contains a bash executable that will be run fail to run in wsl.
Here's where it will break in future updates. The fix is to update the env in windows to the new path since the folder where the exe is located will change to match atom's version.
Add the following in your .bashrc or .zshrc:
Important to be added in .bashrc or .zshrc as making a separate script in /usr/bin will always make atom to open in the C:/Windows folder.
function _atom () { exec nohup atom.exe "$#" &> /dev/null & } # Do not output in terminal and do not block the terminal. Also send the command arguments to atom.
alias atom="_atom"
Open a new wsl terminal.
I wrote a bash script to open atom with and without files from WSL2. It can handle any number (including 0) of file arguments, on any drive. Both relative and absolute paths are supported, but it can't handle path name containing .. or ~. Pointing atom to a director also works as expected. Here's my script:
#!/bin/bash
atom_cmd="/mnt/c/Users/`whoami`/AppData/Local/atom/atom.exe"
for i in "$#"; do
if [[ $i == /mnt* ]]; then
linPath="$i" #for absolute file paths
else
linPath="`pwd`/$i" #for relative file paths
fi
if [[ $linPath == *".."* || $linPath != "/mnt"* || $i == "/home"* ]] ; then
echo "atom script is unacceptable file path $linPath"
continue 1
fi
winPath="\""`echo $linPath | sed -e 's|\/mnt\/\([a-z]\)|\u\1:|' -e 's:\/:\\\\:g'`""
atom_cmd="$atom_cmd $winPath\""
done
unset linPath
unset winPath
echo "command:" "$atom_cmd"
eval "$atom_cmd"
unset atom_cmd
(I'm sure there are things to improve about this, like edge cases and better use of language features. I'd welcome suggestions.)
this can be a little bit outdated but you can simply run a powershell and use:
wsl.exe -d Ubuntu-20.04 //In my case ubuntu
This should open a ubuntu session or whatever wsl you have set on your own.
A little bit nooby on this but trying to help. =)

How can I get Cygwin to accurately read my Windows environment variables?

I'm using Windows XP with the latest version of Cygwin. If I set the following environment variable in my Windows system
JBOSS_HOME=C:/Program Files/jboss-4.2.3.GA
and then fire up Cygwin, I'm unable to switch to the inherited $JBOSS_HOME directory.
$ cd $JBOSS_HOME
cygwin warning:
MS-DOS style path detected: C:/Program
Preferred POSIX equivalent is: /cygdrive/c/Program
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
-bash: cd: C:/Program: No such file or directory
Is it possible to define my system variable once in the Windows environment and then get Cygwin to interpret it so that I don't get this "No such file or directory" warning?
You could do one of two things...
Add a command to convert the path in your .bashrc file, like so...
export JBOSS_HOME=$( cygpath "$JBOSS_HOME" )
or
Just put the variable between quotes when referencing it, since Cygwin understands DOS style paths, even though it doesn't prefer them. The reason the command is failing for you is that there is a space in the path, so putting it in quotes will get the path to be read correctly as one arg...
cd "$JBOSS_HOME"
Note that you might still get that same "cygwin warning" in this case. In order to make that go away, you need to add nodosfilewarning to your CYGWIN var as the warning advises. You can do that by adding this in your .bashrc file...
export CYGWIN="${CYGWIN} nodosfilewarning"
I am using Eclispse with ShellED plugins,
I got the same notification, not knowing the accurate configuration,
I just add the export value into the script
'#!/bin/bash'
export CYGWIN="${CYGWIN} nodosfilewarning"
echo hello
This works for me
$ SEVENZIP="C:/Program Files/7-Zip"
$ read < <(cd "$SEVENZIP"; pwd)
$ cd "$REPLY"

View windows environment variables in Cygwin

Is there a way to sync windows environment variables with Cygwin?
For example, in CMD echo %inetroot% gives the path to a project build. Is it possible to transfer this env variable to Cygwin such that echo $inetroot provides the same path?
Thanks!
Use the env program to so that ... or echo "$inetroot". I think the variable names are case-sensitive, though (in Bash and thus MinGW).
Those variables are all available in MinGW from Windows (user profile and global). Again, use env to list them or for example env|grep -i inetroot to find the properly capitalized version of the variable name.

Resources