18

With the Bourne shell family, the shell variables all have upper-case case names; which means you can't tell if a particular variable is an environment variable or not just by looking at its name. How do you determine which Bourne shell variables are local (defined only within the current shell)?

6
  • 4
    Bourne shell or Bourne-again shell? Can you point to a reference for the uppercase variable thing?
    – Jeff Schaller
    Sep 7, 2017 at 1:57
  • In Bourne-again shell since all variables are uppercase, how can you determine which bash variables are local? Sep 7, 2017 at 2:23
  • 7
    @Shoulderpadz nothing's preventing you from creating lowercase variables.
    – muru
    Sep 7, 2017 at 2:35
  • 1
    By local do you mean variables that have not been exported? Sep 7, 2017 at 2:36
  • 4
    The distinction you are asking about is shell variables vs environment variables, not global vs local. Note that there are shell variables that aren't environment variables (i.e., what you are calling "local"), and there are environment variables that aren't shell variables (the environment can contain names that are not valid shell identifiers, and thus cannot be variables).
    – chepner
    Sep 7, 2017 at 16:18

3 Answers 3

30

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.

19

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"
1

Variables that are NOT exported can be seen from output of declare command in bash.

Variables that are exported can be seen from output of declare -x or export command in bash.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.