The command
export FOO
should, according to my understanding, create an environment variable FOO
(with a blank value) even if this variable did not exist previously and no value was supplied. This position seems to be supported by the zsh
manual. See the following from man zshbuiltins
:
export [ name[=value] ... ]
The specified names are marked for automatic export to the environment of subsequently executed commands. Equivalent
to typeset -gx. If a parameter specified does not already exist, it is created in the global scope.
However, when I use C's getenv
function, this environment variable is not registered. here is a simple example. Consider the following program:
% cat foo.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char* foo = getenv("FOO");
if ( foo == NULL ) {
printf("The environment variable 'FOO' does not exist!\n");
} else {
printf("%s\n", foo);
return 0;
}
}
Compile it:
% gcc --version
gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% gcc foo.c -o foo
Consider the following three executions:
% ./foo
The environment variable 'FOO' does not exist!
% export FOO
% ./foo
The environment variable 'FOO' does not exist!
% export FOO=BAR
% ./foo
BAR
What is wrong in the middle case? Shouldn't it display a blank line?
Note that you didn't need to write your own program to display the env vars. The env
command already exists :-)
This is a quirk that dates back at least four decades to the earliest UNIX shells. Modern shells (including bash, zsh, and ksh) all exhibit that quirk. The quirk is that if you export VAR
and VAR
has not already been assigned a value it is marked to be exported but will not actually be in the exported environment until you assign it a value. You can see this for yourself using any of those shells; not just zsh:
$ export FOO
$ env | grep FOO
$ FOO=''
$ env | grep FOO
FOO=
$ FOO=bar
$ env | grep FOO
FOO=bar
$ BAR=''
$ export BAR
$ env | grep BAR
BAR=
That last example hints at why export
behaves this way.