Special Shell Variables

Some shell variables should not be used, since they can have a deep influence on the behavior of the shell. In order to recover a sane behavior from the shell, some variables should be unset, but unset is not portable (the section called “Limitations of Shell Builtins”) and a fallback value is needed. We list these values below.

CDPATH

When this variable is set cd is verbose, so idioms such as abs=`cd $rel pwd` break because abs receives the path twice.

Setting CDPATH to the empty value is not enough for most shells. A simple path separator is enough except for zsh, which prefers a leading dot:

zsh-3.1.6$ mkdir foo  (CDPATH=: cd foo)
/tmp/foo
zsh-3.1.6$ (CDPATH=:. cd foo)
/tmp/foo
zsh-3.1.6$ (CDPATH=.: cd foo)
zsh-3.1.6$

(of course we could just unsetCDPATH, since it also behaves properly if set to the empty string).

Life wouldn't be so much fun if bash and zsh had the same behavior:

bash-2.02$ mkdir foo  (CDPATH=: cd foo)
bash-2.02$ (CDPATH=:. cd foo)
bash-2.02$ (CDPATH=.: cd foo)
/tmp/foo

Of course, even better style would be to use PATH_SEPARATOR instead of a :. Therefore, a portable solution to neutralize CDPATH is

CDPATH=${ZSH_VERSION+.}$PATH_SEPARATOR

Note that since zsh supports unset, you may unset CDPATH using PATH_SEPARATOR as a fallback, see the section called “Limitations of Shell Builtins”.

IFS

Don't set the first character of IFS to backslash. Indeed, Bourne shells use the first character (backslash) when joining the components in "$@" and some shells then re-interpret (!) the backslash escapes, so you can end up with backspace and other strange characters.

The proper value for IFS (in regular code, not when performing splits) is SPCTABRET. The first character is especially important, as it is used to join the arguments in @*.

LANG, LC_ALL, LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_NUMERIC, LC_TIME

Autoconf-generated scripts normally set all these variables to C because so much configuration code assumes the C locale and posix requires that LC_ALL be set to C if the C locale is desired. However, some older, nonstandard systems (notably sco) break if LC_ALL is set to C, so when running on these systems Autoconf-generated scripts first try to unset the variables instead.

LANGUAGE

LANGUAGE is not specified by posix, but it is a gnu extension that overrides LC_ALL in some cases, so Autoconf-generated scripts set it too.

LINENO

Most modern shells provide the current line number in LINENO. Its value is the line number of the beginning of the current command. Autoconf attempts to execute configure with a modern shell. If no such shell is available, it attempts to implement LINENO with a Sed prepass that replaces the each instance of the string $LINENO (not followed by an alphanumeric character) with the line's number.

You should not rely on LINENO within eval, as the behavior differs in practice. Also, the possibility of the Sed prepass means that you should not rely on $LINENO when quoted, when in here-documents, or when in long commands that cross line boundaries. Subshells should be OK, though. In the following example, lines 1, 6, and 9 are portable, but the other instances of LINENO are not:

$ cat lineno
echo 1. $LINENO
cat EOF
3. $LINENO
4. $LINENO
EOF
( echo 6. $LINENO )
eval 'echo 7. $LINENO'
echo 8. '$LINENO'
echo 9. $LINENO '
10.' $LINENO
          $ bash-2.05 lineno
1. 1
3. 2
4. 2
6. 6
7. 1
8. $LINENO
9. 9
10. 9
$ zsh-3.0.6 lineno
1. 1
3. 2
4. 2
6. 6
7. 7
8. $LINENO
9. 9
10. 9
$ pdksh-5.2.14 lineno
1. 1
3. 2
4. 2
6. 6
7. 0
8. $LINENO
9. 9
10. 9
$ sed '=' lineno |
   sed '
     N
     s,$,-,
     : loop
     s,^\([0-9]*\)\(.*\)[$]LINENO\([^a-zA-Z0-9_]\),\1\2\1\3,
     t loop
     s,-$,,
     s,^[0-9]*\n,,
   ' |
   sh
1. 1
3. 3
4. 4
6. 6
7. 7
8. 8
9. 9
10. 10

NULLCMD

When executing the command foo, zsh executes $NULLCMD foo. The Bourne shell considers NULLCMD is :, while zsh, even in Bourne shell compatibility mode, sets NULLCMD to cat. If you forgot to set NULLCMD, your script might be suspended waiting for data on its standard input.

status

This variable is an alias to $? for zsh (at least 3.1.6), hence read-only. Do not use it.

PATH_SEPARATOR

If it is not set, configure will detect the appropriate path separator for the build system and set the PATH_SEPARATOR output variable accordingly.

On DJGPP systems, the PATH_SEPARATOR environment variable can be set to either : or ; to control the path separator bash uses to set up certain environment variables (such as PATH). Since this only works inside bash, you want configure to detect the regular dos path separator (;), so it can be safely substituted in files that may not support ; as path separator. So it is recommended to either unset this variable or set it to ;.

RANDOM

Many shells provide RANDOM, a variable that returns a different integer when used. Most of the time, its value does not change when it is not used, but on irix 6.5 the value changes all the time. This can be observed by using set.