Here are some workarounds:
$ comm -3 <(declare | sort) <(declare -f | sort)
breakdown:
declare
prints every defined variable (exported or not) and function.
declare -f
prints only functions.
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 workaround:
$ 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 workaround, 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.