40

Reading about this question: In zsh how can I list all the environment variables?, I wondered, how can I list all the shell variables?

Also, does the distinction between shell variables and environment variables apply to shells other than zsh?

I am primarily interested in Bash and Zsh, but it would be great to know how to do this in other mainstream shells.

Josh
  • 1,694
  • 3
  • 16
  • 32
  • A general warning related to most methods: When using such things in scripts, beware variables whose value contains a newline, e.g. IFS. Their representation in the output may span multiple lines. – Palec May 24 '23 at 17:48

4 Answers4

42

List all shell variables

bash : use set -o posix ; set. The POSIX options is there to avoid outputting too much information, like function definitions. declare -p also works.

zsh : use typeset

Shell variables and environment variables

An environment variable is available to exec()-ed child processes (as a copy. if parent process change the variable, the child environment is not updated). A non-environment variable is only available to the current running shell and fork()-ed subshells. This distinction is present in all shells.

(completed thanks to comments)

Uriel
  • 1,343
  • 11
  • 15
  • 1
    The question also has an answer here : http://stackoverflow.com/questions/1305237/how-to-list-variables-declared-in-script-in-bash – Uriel Dec 26 '14 at 14:05
  • 2
    `set -o posix` doesn't exist in zsh; `set` doesn't output function definitions. – vinc17 Dec 26 '14 at 14:33
  • 1
    `set -o posix` is a syntax error in most shells. – mikeserv Dec 26 '14 at 18:29
  • 3
    Shell variables are also available in child processes. The difference comes when the child process executes a new program: environment variables are passed along in `exec`, shell variables are not. – Barmar Dec 31 '14 at 19:03
  • @Barmar if shell variable are not passed, then their content is not available in child processes, no ? – Uriel Dec 31 '14 at 21:06
  • When a process forks, all its memory is duplicated. This includes shell variables. They're not lost until the child process calls `exec` to run an external program. Then only environment variables are passed. – Barmar Dec 31 '14 at 21:15
  • Try: `var=1; (set)`. The parentheses fork a subshell. You'll see `var=1` in the output. – Barmar Dec 31 '14 at 21:17
  • @Barmar Indeed, that is an interesting case. I cannot find other situations where there is no `exec()` after the original shell `fork()`s, that's why I made the shorcut about availability of environment variables. You have other cases like this in mind ? – Uriel Jan 01 '15 at 22:26
  • I'm just trying to make the answer more accurate. For the purposes of contrasting shell variables with environment variables, it's important to distinguish between forking and execing. – Barmar Jan 01 '15 at 23:35
  • 1
    In bash: `declare -px` or simply `declare -x` will print only exported variables. –  Nov 21 '18 at 03:59
19

There are many alternatives:

printenv

Print the values of the specified environment VARIABLE(s). If no VARIABLE is specified, print name and value pairs for them all.

env

env - run a program in a modified environment

export

Set an environment variable. Mark each name to be passed to child processes in the environment.....

-p Display output in a form that may be reused as input.

If no names are supplied, or if the `-p' option is given, a list of exported names is displayed.

set

is useful to get shell variables as well.

If you need extra info (integer, exported) you should instead use

typeset

export has an advantage, that its output can be immediately read back onto the shell.

Lastly, there is

compgen -v

Display possible completions depending on the options.

which shows all variables, shell and environment, without their value or extra info. You will have to echo $VARIABLE_NAME to find the variable value. But at least the list is complete. It belongs to bash, not zsh.

MariusMatutiae
  • 4,363
  • 1
  • 23
  • 36
  • 1
    `export` has no advantage over `set`, at least, when it comes to quoting for shell re-entry. And `printenv` and `env` are not at all about shell variables, though these do often coincide with environment variables. – mikeserv Dec 26 '14 at 17:05
  • 1
    `compgen -e` displays only exported shell variables. Details and other options in [this answer](https://unix.stackexchange.com/a/151120/119895). – Ethan Jan 29 '23 at 06:06
4

With zsh, you can use typeset, which gives more information than set, e.g. the type of the variables. You can still filter the output with grep or sed, depending on what you want. Environment variables are marked as exported in the output.

vinc17
  • 11,912
  • 38
  • 45
1

I had just needed listing only the variables, not their values. For this, I used

env | awk -F '=' '{ print $1 }'

To have all of them in a single line

env | awk -F '=' '{ print $1 }' | tr '\n' ' '
  • OP was asking about the "shell variables" rather than the environment variables. Your info about how to only show the variable names is a useful addition to the discussion. `set -o posix ; set | awk -F '=' '{ print $1 }'` would be just the shell variable names. Thanks! – Wayne Walker Jun 27 '20 at 04:45