This question already has an answer here:

On my search for a command to list all shell variables, I somehow realized, that there is a command to list all environment variables, but somehow there is no one to list all shell variables, for reasons unknown to me.

However, someone here gave an answer on how to display all variables, shell and environment ones.

( set -o posix ; set ) | less

He actually did not explain for the layman what this expression does, and my fragmentary understanding is not enough to grasp the idea behind it.

This is what I know:

  • ( command1; command2) this causes the commands to be executed inside a child process of the shell.
  • set is some way to declare variables, though do not know what the -o posix means and why a second set is executed in succession

  • command | less This one is not the problem, even I understand it, it is a pager for more control about the output.

marked as duplicate by Christopher, Kusalananda, DarkHeart, heemayl, Satō Katsura May 11 '17 at 5:41

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


set shows all shell variables (exported or not). In Bash, set -o posix sets the shell in POSIX compatibility mode. (I don't know if other shells have similar syntax for the similar feature, but I'll assume Bash here.)

The difference in this case is that usually Bash's set shows also shell functions, but in POSIX mode set only shows variables, and changes the output format slightly:

  1. When the set builtin is invoked without options, it does not display shell function names and definitions.
  2. When the set builtin is invoked without options, it displays variable values without quotes, unless they contain shell metacharacters, even if the result contains nonprinting characters.

In Bash, there's additionally the declare builtin that can be used to show all the otherwise hidden or Bash-specific flags of variables: declare -p xx shows variable xx in a format that Bash can take as input. declare -p shows all variables and declare -f can be used to show functions.

  • So, the gnu/linux whizzkids were some kind of lying to me. there is a simple command to list all shell variables: set. but it lists additionally shell functions. – sharkant May 10 '17 at 20:13
  • with printenv i saw only lines that looked like variables, does this mean printenv only shows environment variables and no environment functions or does something like environment functions not exist at all? – sharkant May 10 '17 at 20:16
  • 1
    @sharkant, there's a command called printenv in GNU coreutils and (like env) as an external program, it can only show variables exported to the environment, not those internal to the shell. I think (t)csh also has a built-in printenv but that also seems to only show environment variables. – ilkkachu May 10 '17 at 20:25
  • 1
    @sharkant, also, at least Bash can export functions to subshells, of course it does so by encoding them in environment variables. There's export -f to enable exporting a function. That feature was the source of an infamous security vulnerability a while back. – ilkkachu May 10 '17 at 20:28

There's two things going on basically: the set commands are being called in subshell to avoid messing up your current shell options, and that subshell is being set to POSIX mode before listing all the variables. To quote the manual:

posix Change the behavior of bash where the default operation differs from the POSIX standard to match the standard (posix mode). See SEE ALSO below for a reference to a document that details how posix mode affects bash's behavior.

In short, bash in POSIX mode will behave closer to what sh does.

As for option-less set, it's also in the manual and it actually states the reason why POSIX mode is necessary:

set [+abefhkmnptuvxBCEHPT] [+o option-name] [arg ...] Without options, the name and value of each shell variable are displayed in a format that can be reused as input for setting or resetting the currently-set variables. . .In posix mode, only shell variables are listed.

...as opposed to variables and function definitions, which is what's done whenbash is in regular mode.

See this for more info about POSIX mode.

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