What is the difference between calling a command via “wsl [command]” and opening a wsl shell and calling “[command]”?

To be honest, when I first looked at this question, I thought it would be an easy answer. Oh how wrong I was. There are a lot of nuances to how this works.

Let’s start with the fairly “easy” part, though. The main difference between the first method and the second:

  • wsl by itself launches into a login (and interactive) shell
  • the shell launched with wsl echo $PATH is neither a login shell nor an interactive shell

So the first will source both login scripts (e.g. ~/.profile) and interactive startup scripts (e.g. ~/.bashrc). The second form does not get to source either of these.

You can see this a different way (and get to the solution) with the following commands:

  • wsl -e bash -c 'echo $PATH'
  • wsl -e bash -li -c 'echo $PATH'

The -li forces bash to run as a login and interactive shell, thus sourcing all of the applicable startup scripts. And, as @bovquier points out in the comments, a single quote is needed here to prevent PowerShell from interpolating the $ before it gets to Bash. That, or escape it.

You should be able to run TeX Live the same way, just replacing the “echo $PATH” with the startup command you need for TeX Live.

A second option would be to create a script that both adds the path and runs the command, and just launch that script through wsl /path/to/script.sh

That said, I honestly don’t think that your current login/interactive PATH is coming from /etc/environment. In my testing, at least, /etc/environment has no use in WSL, and that’s to be expected. /etc/environment is only sourced by PAM modules, and with no login check performed by WSL, there’s no reason to invoke PAM in either the wsl nor the wsl echo $PATH commands.

I’d expect that you still have the PATH setting in ~/.bashrc or somewhere similar), and that’s where the shell is picking it up from at the moment.

While this isn’t necessarily critical to understanding the answer, you might also wonder, if /etc/environment isn’t used for setting the default (non-login, non-interactive) path in WSL, what is? The answer seems to be that it is hard-coded into the init that starts up WSL. That init is also what appends the Windows path (assuming you don’t have that feature disabled in /etc/wsl.conf).

Leave a Comment