Bash – Why does bash clear OLDPWD when a child script is started

bashenvironment-variables

OLDPWD is exported and passed to any children, but bash apparently clears OLDPWD whenever a child script is started:

$ cd /etc
$ cd
$ perl -e 'print "<$ENV{OLDPWD}>\n"'
</etc>
$ ksh  -c 'echo "<$OLDPWD>"'
</etc>
$ bash -c 'echo "<$OLDPWD>"'
<>

Any way to work around that other than creating an alias or dotting the child script or exporting some other variable with the same value, whenever I want to use $OLDPWD in a child script?

** UPDATE 2015/11/26 **

I filed a bash bug report and got this reply from Chet Ramey, the bash maintainer:

Why does bash clear OLDPWD when a child script is started?

Because a new shell does not have a `previous working directory'.
It's supposed to be set by cd, and if you haven't executed cd, you
don't have one.

It seems reasonable to inherit OLDPWD if it names a directory, in
the same way that the shell inherits PWD if it names the current
directory, so we'll try that for the next bash version.

Best Answer

Probably this is leftover behavior from long ago when bash first implemented OLDPWD. The release notes for bash 2.03 alpha (in 1999) indicate that OLDPWD was previously not an exported variable. If it was not exported, it would not be inherited by a child process.

Judging by the comment on this chunk from bash's source, the behavior is intentional:

  /* According to the Single Unix Specification, v2, $OLDPWD is an
     `environment variable' and therefore should be auto-exported.
     Make a dummy invisible variable for OLDPWD, and mark it as exported. */
  temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
  VSETATTR (temp_var, (att_exported | att_invisible));

Though the release note indicates that making it exported was done to follow POSIX.2, OLDPWD does not appear in the list of shell variables for POSIX shell. It does appear in the description of cd. That does not mention if an initial value should be obtained from a parent process; there is no specific behavior which is required.

It does not appear to be a documented feature of bash; there are few comments to be found:

Related Question