Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

The bash builtin command set, if invoked without arguments, will print all shell and environment variables, but also all defined functions. This makes the output unusable for humans and difficult to grep.

How can I make the bash builtin command set print only the variables and not the functions?

Are there other commands which prints only the shell variables, without the functions?

Note: bash differentiates between shell variables and environment variables. see here Difference between environment variables and exported environment variables in bash

share|improve this question

6 Answers 6

up vote 15 down vote accepted

Here is a solution, inspired by the previous answers:

$ comm -3 <(declare | sort) <(declare -f | sort)

breakdown:

  1. declare prints every defined variable (exported or not) and function.
  2. declare -f prints only functions.
  3. comm -3 will remove all lines common to both. In effect this will remove the functions, leaving only the variables.

To only print variables which are not exported:

$ comm -3 <(comm -3 <(declare | sort) <(declare -f | sort)) <(env | sort)

Another solution:

$ declare -p

This will only print the variables, but with some ugly attributes.

declare -- BASH="/bin/bash"
declare -ir BASHPID=""
declare -A BASH_ALIASES='()'
declare -a BASH_ARGC='()'
...

You can cut the attributes away using... cut:

$ declare -p | cut -d " " -f 3

One downside is that the value of IFS is interpreted instead of displayed.

compare:

$ comm -3 <(declare | sort) <(declare -f | sort)
...
IFS=$' \t\n'
...
$ declare -p | cut -d " " -f 3
...
IFS="
"
...

This makes it quite hard to use that output for further processing, because of that lone " in one line. Perhaps some IFS-fu can be done to prevent this.


Yet another solution, using compgen:

$ compgen -v

The bash builtin compgen was meant to be used in completion scripts. To this end, compgen -v lists all defined variables. The downside: it lists only the variable names, not the values.

Here is a hack to also list the values.

$ compgen -v | while read var; do printf "%s=%q\n" "$var" "${!var}"; done

The advantage: it is a pure bash solution. The disadvantage: some values are messed up because of the interpretation through printf. Also the subshell from the pipe and/or the loop add some extra variables.

share|improve this answer
    
does your declare ...| cut pipe break if there are no attributes for a variable? I'm guessing that -- is used in that case, but I'm still uneasy. sed might be safer, i.e. declare -p | sed 's/^.* \([^ ]\+\)$/\1/' –  jmtd May 12 '11 at 14:29
    
+1 for compgen :) –  RSFalcon7 Mar 6 at 23:55

The typeset builtin strangely has an option to show functions only (-f) but not to show parameters only. Fortunately, typeset (or set) displays all parameters before all functions, function and parameter names cannot contain newlines or equal signs, and newlines in parameter values are quoted (they appear as \n). So you can stop at the first line that doesn't contain an equal sign:

set | awk -F '=' '! /^[0-9A-Z_a-z]+=/ {exit} {print $1}'

This only prints the parameter names; if you want the values, change print $1 to print $0.

Note that this prints all parameter names (parameters and variables are used synonymously here), not just environment variables (“environment variable” is synonymous with “exported parameters”).

Note also that this assumes there is no environment variable with a name that doesn't match bash's constraints on parameter names. Such variables cannot be created inside bash but can have been inherited from the environment when bash starts:

env 'foo ()
{
  =oops' bash
share|improve this answer
    
Great solution! I didn't even think of just stopping at the first line that doesn't have a '='. +1 –  Steven D Oct 27 '10 at 3:34

I am unsure how one can make set print only variables. However by looking at the output of set, I was able to come up with the following that seems to grab just variables:

$ set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" 

Basically, I am looking for lines that start with letters, numbers, or punctuation followed by a "=". From the output that I saw, this grabs all of the variables; however, I doubt that this is very portable.

If, as your title suggests, you want to subtract from this list the variables that are exported and thus get a list of non-exported variables, then you could do something like this

$ set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" | sort > ./setvars && env | sort | comm -23 ./setvars - 

To break this down a bit, here is what it does:

  1. set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" | sort > ./setvars : This hopefully gets all of the variables (as discussed before), sorts them, and sticks the result in a file.
  2. && env | sort: After the previous command is complete, we are going to call env and sort its output.
  3. | comm -23 ./setvars -: Finally, we pipe the sorted output of env into comm and use the -23 option to print the lines that are unique to the first argument, in this case the lines unique to our output from set.

When you are done you might want to cleanup the temp file that it created with the command rm ./setvars

share|improve this answer
    
The problem with your command is not portability (it's specific to bash, of course, but there's no problem on the grep side). The problem is that you're grabbing some lines in function definitions. Bash indents most of the function code, but not all of it, in particular not text inside here documents (f () {|cat <<EOF|foo=bar|EOF|} where | represents a line break). –  Gilles Oct 26 '10 at 19:01

"Are there other commands which prints only the shell variables, without the functions?"

In man bash, in section SHELL BUILTIN COMMANDS (in the set section) it says: "In posix mode, only shell variables are listed."

(set -o posix; set)

I know that the question has been answered but (set -o posix; set) is cleaner then most suggestions.

share|improve this answer
    
By far the best solution –  Ruslan May 25 at 9:27

Just use the command env. It does not print functions.

share|improve this answer
    
It does if used inside a script. –  DocSalvage Sep 5 '13 at 13:08

Try the command printenv:

$printenv
share|improve this answer
    
printenv and env only print exported (environment) variables and not non-exported (shell) variables. –  Lri Jun 5 '13 at 7:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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