In a posix-compatible way that works with multiple implementations, how can I print the list of currently defined environment variable without their values?
On some implementations (mksh, freebsd /bin/sh), just using export
by itself will fit the bill:
$ export
FOO2
FOO
But for some other implementations (bash, zsh, dash), export
also shows the value. With bash, for example:
$ export
export FOO2='as df\
asdk=fja:\
asd=fa\
asdf'
export FOO='sjfkasjfd kjasdf:\
asdkj=fkajdsf:\
:askjfkajsf=asdfkj:\
safdkj'
$ printenv | sed -n l
FOO2=as\tdf\$
asdk=fja:\$
asd=fa\$
asdf$
FOO=sjfkasjfd kjasdf:\$
asdkj=fkajdsf:\$
\t:askjfkajsf=asdfkj:\$
safdkj$
Other options like env
or printenv
don't have options to print just the variable names without values, at least not on the linux and freebsd platforms I have tried.
Piping to awk/sed/etc. or trimming the list with parameter expansion techniques (e.g., ${foo%%=*}
) is acceptable, but it has to work with values that may span lines and have =
and whitespace in the value (see example above).
Answers specific to particular shell implementations are interesting, but I am primarily looking for something that is compatible across implementations.
Best Answer
It's pretty easy in awk.
However beware some awk implementations add environment variables of their own (e.g. GNU awk adds
AWKPATH
andAWKLIBPATH
toENVIRON
).The output is ambiguous if the name of an environment variable contains a newline, which is extremely unusual but technically possible. A pure sh solution would be difficult. Your best bet is to start with
export -p
but massaging it in pure sh is difficult. You can use sed to massage the output ofexport -p
, then useeval
to get the shell to remove what it quoted. Bash and zsh print non-standard prefixes.Note that depending on the shell,
export -p
may or may not show variables whose name is not valid in the shell, and if it doesn't, then it may or may not quote the names properly. For example, dash, mksh and zsh omit variables whose name includes a newline, BusyBox dash and ksh93 print them raw, and bash prints them raw without their value. If you need to defend against untrusted input, don't rely on a pure POSIX solution, and definitely don't calleval
on anything derived from the output ofexport -p
.