cenvironment-variableszshgetenv

zsh export with one argument does not seem to actually create environment variable


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?


Solution

  • 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.