How do you determine whether shell variables are exported or not?

The most portable way is export -p.

export -p lists exported variables. This is usually like declare -x, if your shell has declare.

Bourne-style shells currently in use should support export -p, as it is required by POSIX:

When -p is specified, export shall write to the standard output the names and values of all exported variables, in the following format:

"export %s=%s\n", <name>, <value>

if name is set, and:

"export %s\n", <name>

if name is unset.

The standard goes on to explain that the value of the variable is displayed in such a way that usually allows it to be used later on the right-hand side of = in an assignment. This is to say that it may be quoted. Different shells may display them differently but with the same effect. export -p works even in shells that have no declare builtin, like Dash.

$ dash -c 'export -p | grep HOME='  # busybox sh and other ash give the same output.
export HOME='/home/ek'
$ posh -c 'export -p | grep HOME='  # ksh93, mksh, lksh, and others give the same output.
export HOME=/home/ek

I've piped the output to grep for compactness but if you don't filter it then you get the full list of your exported variables. From your question, it sounds like that's what you might find most useful.

Some shells, like Bash, use a non-standard format unless explicitly instructed to behave in a POSIX-compliant manner. In Bash export -p gives the same output as declare -x by default.

$ bash -c 'export -p | grep HOME='
declare -x HOME="/home/ek"
$ bash -c 'POSIXLY_CORRECT= export -p | grep HOME='
export HOME="/home/ek"
$ bash -c 'set -o posix; export -p | grep HOME='
export HOME="/home/ek"
$ bash --posix -c 'export -p | grep HOME='
export HOME="/home/ek"
$ ln -s /bin/bash sh
$ ./sh -c 'export -p | grep HOME='  # Invoking bash as sh also puts it in POSIX mode.
export HOME="/home/ek"

Zsh shows a non-standard format even when POSIX compatibility is enabled:

$ zsh -c 'export -p | grep HOME='
typeset -x HOME=/home/ek
$ zsh -c 'emulate -R sh; export -p | grep HOME='
typeset -x HOME=/home/ek
$ ln -s /bin/zsh sh
$ ./sh -c 'export -p | grep HOME='
typeset -x HOME=/home/ek

In any case, you can extract portable representations (which may be quoted) by searching for a word followed by =. This doesn't rely on previous words on the line, so long as they don't immediately precede =, which they shouldn't. For example:

% export -p | grep -oE '\w+=.*'
HOME=/home/ek
LANG=en_US.UTF-8
LESSCLOSE='/usr/bin/lesspipe %s %s'
....

Note that not all entries necessarily have =. This is because variables can be unset but exported. Those entries are filtered out by the grep command above, which may or may not be what you want.

Most of the time, you just want to inspect the output and so you won't care if the entries are preceded by export, declare -x, typeset -x, or something else. Then just run export -p.

I tested those commands on Ubuntu 16.04 LTS with officially packaged versions of each shell.


If you want see if a variable is exported or not, use declare:

$ foo=a bar=b
$ export foo
$ declare -p foo bar
declare -x foo="a"
declare -- bar="b"

Tags:

Shell

Bash