opscape

System and users

printenv

Print all environment variables, or the values of the ones you name.

printenv [-0] [VARIABLE...]

8 of 8 examples run in Debian 13.7 on 2026-10-31 · coreutils 9.7-3 · manual: printenv(1)

printenv prints the environment it received. With no arguments the output looks like env's; with names it prints only their values, one per line, and its exit status says whether every name was found. That makes it a clean way to check for a variable in a script without the ambiguity of echo "$VAR", which prints an empty line both for an empty variable and for one that does not exist.

Because it is a separate program, printenv sees only exported variables, exactly what any child process would see. That is its most useful property when debugging: if printenv FOO shows nothing, the program you are about to start will not see FOO either, however echo $FOO looks in your shell.

Examples

Print the whole environment

printenv
explain
output
SHELL=/bin/bash
EDITOR=vi
PWD=/home/dev/demo
LOGNAME=dev
TZ=UTC
HOME=/home/dev
LANG=C.UTF-8
COLUMNS=80
TERM=dumb
USER=dev
SHLVL=0
PATH=/usr/local/bin:/usr/bin:/bin
_=/usr/bin/printenv

Every exported variable as NAME=value, in no particular order.

Print one variable's value

printenv HOME
explain
output
/home/dev

Only the value is printed, without the name, so it can be captured with $(...).

Print several values

printenv USER SHELL TZ
explain
output
dev
/bin/bash
UTC

One value per line, in the order you asked for.

Ask for a variable that is not set

printenv DATABASE_URL; echo "exit: $?"
explain
output
exit: 1

Nothing is printed and the exit status is 1. When several names are given, the status is 1 if any of them is missing.

Stop a script when a required variable is missing

for v in HOME API_TOKEN; do
  printenv "$v" >/dev/null || { echo "error: $v is not set" >&2; exit 1; }
done
echo "all set"
outputexit 1
error: API_TOKEN is not set

The exit status drives the check, so an empty-but-set variable still counts as present. API_TOKEN is missing here, so the loop stops with status 1.

See the difference between a shell variable and an exported one

region=eu-west
printenv region || echo "not exported yet"
export region
printenv region
output
not exported yet
eu-west

A plain assignment creates a shell variable that child processes, including printenv, cannot see. After export it becomes part of the environment.

Show variables whose names match a pattern

printenv | grep -E '^(LANG|LC_|TZ)'
explain
output
TZ=UTC
LANG=C.UTF-8

Filtering on ^NAME matches names only, not values. Here: the locale and time zone settings that affect sorting and dates.

Check what a .env file adds

cat .env
set -a; . ./.env; set +a
printenv API_URL DEBUG
output
API_URL=http://localhost:8080
DEBUG=false
http://localhost:8080
false

set -a exports every variable assigned while it is on, so sourcing a KEY=value file makes the values visible to printenv and to any program started afterwards.

Common pitfalls

  • Writing printenv $HOME. The argument is a variable name: printenv HOME. With $, the shell substitutes the value and printenv looks for a variable called /home/dev.

  • Concluding a variable is unset because printenv shows nothing, when it is only unexported. declare -p NAME shows shell variables too.

  • Using printenv to check a variable that a script sets for itself. Variables set in the current shell only appear after export.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • BSD and macOS printenv accept only one variable name and have no -0; GNU accepts several. For portability, call it once per variable.

Options worth knowing

A selection, described in our own words. For the full list, see printenv(1) or printenv --help.

OptionWhat it does
-0, --nullEnd each output entry with NUL instead of a newline.
--helpPrint usage and exit.
--versionPrint the coreutils version and exit.

Related