Published in Articles on by Michiel van Oosterhout ~ 4 min read
In this article we will look at how to configure Bash on Windows. We'll set it up so that Bash included in Cygwin (see Git for Windows revisited), Bash included in Git for Windows (see Installing Git on Windows), and Bash included in a Linux distribution running on WSL (see Windows' Subsystem for Linux) all use the same configuration.
 
        Bash startup files
When a new Bash process starts it will processes certain startup files. Simply stated: an interactive shell will process ~/.bashrc. An interactive login shell will process ~/.bash_profile instead.
Interactive shell
An interactive Bash process (interactive shell) is one which reads from and writes to a terminal (for example, Console Window Host or Windows Terminal). Among other things, an interactive shell displays a prompt, enables command line editing, and expands aliases. When the PS1 variable is set the Bash process is likely interactive.
- Bash started from another command-line shell is an interactive shell.
Login shell
A login Bash process (login shell) is one which ensures correct initialization of a login session, such as processing certain startup files that should be processed only once per session. In a Bash login shell the login_shell option is set. A login shell is typically interactive.
- Git Bash started via the Start menu is an interactive login shell (git-bash.exepasses the--loginand-ioptions to Bash).
- Bash running on WSL started via bash.exe,wsl.exe, ordebian.exeis an interactive login shell.
Configuring Bash
We'll need to create the .bash_profile and .bashrc files.
.bash_profile
First we'll create .bash_profile, for login shells. This Bash script will source all Bash scripts found in the $USERPROFILE/.config/bash/login.d directory. This approach ensures we can add new configuration scripts later. After that, the script also sources .bashrc, so that interactive login shells have the same configuration as interactive non-login shells.
# Ensure the directory exists
$path = "$Env:USERPROFILE\.config\bash\login.d"
$_ = New-Item $path -Force -ItemType Directory
# Declare the Bash script contents
$script = @'
dir=${USERPROFILE//\\//}/.config/bash/login.d
if [ -d $dir ]; then
    for file in $dir/*.bash; do
        [ -r $file ] && . $file
    done
fi
file=${USERPROFILE//\\//}/.bashrc
[ -r $file ] && . $file
'@
# Create the Bash script
$path = "$Env:USERPROFILE\.bash_profile"
Set-Content -Path $path -Value $script
# Ensure proper line endings
((Get-Content $path) -join "`n") + "`n" | Set-Content -NoNewline $path
.bashrc
Next we'll create .bashrc, for interactive shells. This Bash script will exit if it is not sourced in an interactive shell, and otherwise it will source all Bash scripts found in the $USERPROFILE/.config/bash/interactive.d directory.
# Ensure the directory exists
$path = "$Env:USERPROFILE\.config\bash\interactive.d"
$_ = New-Item $path -Force -ItemType Directory
# Declare the Bash script contents
$script = @'
[ -z "$PS1" ] && return
dir=${USERPROFILE//\\//}/.config/bash/interactive.d
if [ -d $dir ]; then
    for file in $dir/*.bash; do
        [ -r $file ] && . $file
    done
fi
'@
# Create the Bash script
$path = "$Env:USERPROFILE\.bashrc"
Set-Content -Path $path -Value $script
# Ensure proper line endings
((Get-Content $path) -join "`n") + "`n" | Set-Content -NoNewline $path
WSL
For Bash included in a Linux distribution running on WSL we'll need to do 3 things to ensure it uses the same configuration:
- Add USERPROFILEtoWSLENV
- Source $USERPROFILE/.bash_profilefrom~/.bash_profile
- Source $USERPROFILE/.bashrcfrom~/.bashrc
# Add USERPROFILE to WSLENV
cmd /c setx WSLENV "%WSLENV%:USERPROFILE/pu"
# Source .bash_profile_
wsl echo "[ -r \`"`$USERPROFILE/.bash_profile\`" ] && . \`"`$USERPROFILE/.bash_profile\`"" `> ~/.bash_profile
# Source .bashrd
wsl echo "[ -r \`"`$USERPROFILE/.bashrc\`" ] && . \`"`$USERPROFILE/.bashrc\`"" `> ~/.bashrc
By using the /pu option for the USERPROFILE environment variable, WSL will 'translate' the path to a valid Linux path (e.g. something like /mnt/c/Users/michiel).
Conclusion
With some relatively simple Bash scripts in specific locations it is possible to have single configuration that works for 3 commonly used Bash implementations: Cygwin, Git for Windows, and WSL.