How to get the host user home directory in WSL Bash
I want to get the Windows "host" user home directory from within bash, so my theoretical environment variable (or program)
echo $WINHOME
would output something like
/mnt/c/Users/dualed
Would this be somehow possible?
When I search for it, I only find results for the opposite (finding the LXSS user path from the host)
I have a fallback-idea of extracting it from $PATH
, as there are some predictable paths like those containing AppData
, but I'd prefer to keep it simple, if possible.
With wslpath
and wslvar
:
$ wslpath "$(wslvar USERPROFILE)"
/mnt/c/Users/felipesantos
You may launch cmd.exe
from bash to get the host environment variables.
In the following, win_userprofile
has your answer, and the other variables
are for completeness.
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//\\//}"
Sources : Craig Loewen at Microsoft and Michael Hoffman.
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 name in the WSLENV
variable. If you are not using WSLENV
yet then just run the following command once in a cmd.exe
session. The command setx
permanently writes variables to the master environment in the Windows registry:
setx WSLENV USERPROFILE/up
This WSLENV
setting will cause WSL to make %USERPROFILE%
from Windows accessible as $USERPROFILE
in WSL shell. The Windows directory path will be converted to the Unix format. If you do not want to convert the path, just omit the p
:
setx WSLENV USERPROFILE/u
If you need to transfer multiple variables separate them by a colon. More details:
- https://docs.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
}
Since my writing of this question, the tool wslpath
has been added to WSL/LXSS. This tool can translate windows paths to the corresponding correct (?) mount point on the Linux subsystem, therefore the easiest solution would be now:
export WINHOME=$(wslpath $(cmd.exe /C "echo %USERPROFILE%"))
# echo $WINHOME prints something like /mnt/c/Users/dualed
Also, now it seems possible to cascade environments, so this is now also an option:
export WINHOME=$(cmd.exe /C "cd /D %USERPROFILE% && bash.exe -c pwd")
PS: The wslpath
tool seems extremely alpha:
man wslpath
# No manual entry for wslpath
# See 'man 7 undocumented' for help when manual pages are not available.
wslpath /?
# wslpath: /?: Invalid argument
wslpath -?
# wslpath: unrecognized option: ?
# wslpath: Invalid argument
wslpath --help
# wslpath: unrecognized option: -
# wslpath: Invalid argument
wslpath
# wslpath: Invalid argument
just a small warning.
Hopefully helpful update: Currently I'm using a small helper to retrieve windows environment variables
#!/bin/bash
# 'winenv'
cmd.exe /C "echo %$*%" | tr -d '\r'
And using it like:
WINHOME=$(wslpath "$(winenv USERPROFILE)")
This is my reference answer, should the question not be answerable at this time, or be unclear. It does what I wrote in the question I wanted to avoid - guessing the user's home directory by looking for fields containing AppData
(and a bit more) within $PATH
#!/bin/bash
IFS=':' read -a fields <<<"$PATH"
for field in "${fields[@]}"; do
if [[ $field =~ ^(/mnt/.*)/AppData/Local/.* ]]; then
echo ${BASH_REMATCH[1]}
exit
fi
done
It does require of course that there is at least one path in %APPDATA%
in Windows, and (more problematic in my opinion) that there is no AppData path set with other user names, e.g. in global scope and finally that the home directory is actually mounted in /mnt
.
Example output:
$ winhome
/mnt/c/Users/dualed