What's the difference between "env" and "set" (on Mac OS X or Linux)?
Long story short: set
can see shell-local variables, env
cannot.
Shells can have variables of 2 types: locals, which are only accessible from the current shell, and (exported) environment variables, which are passed on to every executed program.
Since set
is a built-in shell command, it also sees shell-local variables (including shell functions). env
on the other hand is an independent executable; it only sees the variables that the shell passes to it, or environment variables.
When you type a line like a=1
then a local variable is created (unless it already existed in the environment). Environment variables are created with export a=1
If you want to limit the output of the set
command to variables only, you may run it in POSIX mode:
type -a env set
help set
(set -o posix; set) | nl
If you need finer control over listing specific variables, you may use Bash builtins such as declare
or compgen
, or some other Bash tricks.
man bash | less -p '-A action$' # info on complete & compgen
# listing names of variables
compgen -A variable | nl # list names of all shell variables
echo ${!P*} # list names of all variables beginning with P
compgen -A export | nl # list names of exported shell variables
export | nl # same, plus always OLDPWD
declare -px | nl # same
declare -pr # list readonly variables
# listing names of functions
compgen -A function | nl
declare -F | nl
declare -Fx | nl
# show code of specified function
myfunc() { echo 'Hello, world!'; return 0; }
declare -f myfunc
set
is a shell builtin, while env
is a program (/usr/bin/env)
set
does several things, but by itself it lists the environment variables. It can also set/toggle switches, such as set +x
or set -v
etc.
env
by itself lists the exported environment variables, but can run a program in a modified environment
See man 1 env
for more information.