Skip to content
shellmap

envPrint current environment variables or run a command in a clean env across all 5 shells

Equivalents in every shell

Bashunix
env

External binary from coreutils. With no args, dumps every exported variable, one `KEY=VALUE` per line. `env -i bash` starts a fresh bash with an EMPTY environment (useful for reproducing "works on my machine" bugs caused by stray vars). `env FOO=bar mycommand` runs `mycommand` with `FOO` set, without polluting the calling shell. `env -u FOO mycommand` runs without `FOO`. Shell variables that haven't been `export`ed do NOT appear in `env` — they're shell-local, not environment.

Zshunix
env

Same external. Zsh quirk: `typeset` and `declare` are zsh's introspection tools — `typeset -x` lists exported (environment) vars with their flags; `typeset` alone lists shell-local vars `env` won't see. `printenv` is the closely-related coreutils command (slightly different — sees only env, no `-i` / `-u` flags). For a per-command env override that zsh history can replay verbatim, `FOO=bar mycommand` (without `env`) also works.

Fishunix
env

Same external. Fish stores variables differently from POSIX shells — `set -x FOO bar` exports (visible to `env`), `set FOO bar` is fish-local (NOT in `env`). `set -gx` is global+exported. `env | grep PATH` to inspect specific vars from the env. Fish's own `env --help` shows the coreutils binary's help, not anything fish-specific.

PowerShellwindows
Get-ChildItem Env:

The `Env:` PSDrive exposes environment variables as objects — `Get-ChildItem Env:` (alias `gci env:` or `ls env:`) lists them all; `$env:PATH` reads one; `$env:FOO = "bar"` sets one for the current session (NOT persisted — see `[Environment]::SetEnvironmentVariable` with the `User` / `Machine` scope for that). `Get-ChildItem Env: | Sort-Object Name` for an alphabetised view. There is no native pwsh `env -i` — to start a clean-environment subprocess, use `Start-Process pwsh -ArgumentList "-NoProfile","-NoLogo"` and rely on profile / config to define what you want.

cmd.exewindows
set

`set` (no args) lists every environment variable. `set FOO` lists vars starting with `FOO`. `set FOO=bar` sets one for the current cmd session (cleared on exit). For persistent set use `setx FOO bar` (writes to the user registry, takes effect in NEW cmd sessions — does NOT affect the current one). `set FOO=` (empty value) unsets in-session. There is no native cmd analog to `env mycommand FOO=bar` — wrap with `set FOO=bar & mycommand` (sets in current session) or use pwsh.

Worked examples

Show all environment variables

Bash
env
Zsh
env
Fish
env
PowerShell
Get-ChildItem Env:
cmd.exe
set

Run a command with one variable temporarily overridden

Bash
env DEBUG=1 npm test
Fish
env DEBUG=1 npm test
PowerShell
$env:DEBUG = "1"; npm test; Remove-Item Env:DEBUG
cmd.exe
set DEBUG=1 && npm test && set DEBUG=

Start a subprocess with a completely empty environment

Bash
env -i bash
Fish
env -i fish
PowerShell
Start-Process pwsh -ArgumentList "-NoProfile"

Gotchas

  • Shell variables and environment variables are NOT the same. `FOO=bar` (bash, no `export`) sets a SHELL-LOCAL variable that won't appear in `env` and won't be inherited by subprocesses. `export FOO=bar` (bash) or `set -x FOO bar` (fish) makes it part of the environment. The same trap exists in pwsh: `$FOO = "bar"` is a session var; `$env:FOO = "bar"` is the environment.
  • pwsh `$env:FOO = "bar"` is session-only — closing the terminal loses it. For PERSISTENT, use `[Environment]::SetEnvironmentVariable("FOO", "bar", "User")` (registry-backed, available in future sessions) or `"Machine"` scope (HKLM, requires admin, affects all users). The same applies to `cmd` `set` (session) vs `setx` (persistent registry write).
  • On Windows, `Path` is the conventional env-var name (mixed case); on Unix, `PATH` (all caps). pwsh `$env:PATH` and `$env:Path` both work because Windows env vars are case-insensitive. On WSL / Linux pwsh, they're case-sensitive — `$env:PATH` succeeds, `$env:Path` may return `$null`. Use the all-caps form for portable scripts.
  • cmd `set FOO=bar & mycommand` runs `mycommand` with `FOO=bar`, but the trailing `& set FOO=` is mandatory if you don't want `FOO` to leak into subsequent commands in the same cmd window. The bash `env FOO=bar mycommand` form is automatic — the var only exists for that one process. cmd does NOT have an equivalent one-shot syntax.
  • `env` (the binary) is ALSO the shebang interpreter — `#!/usr/bin/env python3` looks up `python3` on `$PATH` rather than hard-coding `/usr/bin/python3`. This is the portable way to write Unix scripts. The shebang does NOT respect alias / function definitions — it only does a `$PATH` lookup. If `python3` is a shell function, the shebang line won't find it.

WSL & PowerShell Core notes

pwshThe `Env:` PSDrive works identically on Windows, Linux, and macOS pwsh — `$env:HOME`, `$env:USER` (Unix-style) on pwsh / Linux, `$env:USERPROFILE`, `$env:USERNAME` on Windows. Portable scripts often need both: `$home = $env:HOME ?? $env:USERPROFILE`. `[Environment]::GetEnvironmentVariables()` returns a hashtable on every pwsh and is a clean, scriptable alternative to `Get-ChildItem Env:`.
WSLWSL bash and Windows pwsh have COMPLETELY separate environments — `env` inside WSL shows the WSL-side vars; `cmd /c set` from inside WSL shows the Windows side. The `WSLENV` env var is the bridge: set `WSLENV=FOO/u` on the Windows side to forward `FOO` to WSL bash on `wsl.exe` invocation (the `/u` suffix means "translate Windows path to Unix path"). Without `WSLENV` entries, vars don't cross the boundary.

Related glossary

Common tasks using env

Related commands