The Computer Oracle

How to get the host user home directory in WSL Bash

--------------------------------------------------
Become or hire the top 3% of the developers on Toptal https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Romantic Lands Beckon

--

Chapters
00:00 Question
00:50 Accepted answer (Score 37)
01:04 Answer 2 (Score 9)
02:39 Answer 3 (Score 5)
03:11 Answer 4 (Score 4)
04:53 Thank you

--

Full question
https://superuser.com/questions/1271205/...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#windowssubsystemforlinux

#avk47



ACCEPTED ANSWER

Score 39


With wslpath and wslvar:

$ wslpath "$(wslvar USERPROFILE)"
/mnt/c/Users/felipesantos



ANSWER 2

Score 9


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:


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
}



ANSWER 3

Score 5


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.




ANSWER 4

Score 4


Since my writing of this question, wslpath has been added to (to my knowledge) all WSL/LXSS distributions. This program can translate windows paths to the corresponding mount point on the Linux subsystem, therefore the easiest solution would be now:

export WINHOME=$(wslpath $(cmd.exe /C "echo %USERPROFILE%" 2>/dev/null | tr -d '\r'))
# echo $WINHOME prints something like /mnt/c/Users/dualed

wslpath documentation is still sparse:

$> man wslpath
# No manual entry for wslpath
# See 'man 7 undocumented' for help when manual pages are not available.

$> wslpath --help
wslpath: unrecognized option: -
wslpath: Invalid argument
Usage:
    -a    force result to absolute path format
    -u    translate from a Windows path to a WSL path (default)
    -w    translate from a WSL path to a Windows path
    -m    translate from a WSL path to a Windows path, with '/' instead of '\'

EX: wslpath 'c:\users'

Notes

  • Windows commands often add carriage-return to the output which is also not removed by wslpath, and so may end up in the Linux output, tr -d '\r' gets rid of that
  • For some time now, cmd.exe will print a warning message to stderr that it was started from an invalid directory, the 2>/dev/null part removes that

Currently I'm using a small helper to retrieve any windows environment variable

#!/bin/bash
# 'winenv'
cmd.exe /C "echo %$*%" 2>/dev/null | tr -d '\r'

And using it like this

WINHOME=$(wslpath "$(winenv USERPROFILE)")