[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
11.10 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; M4sh takes
care of this and provides fallback values, whenever needed, to cater
for a very old ‘/bin/sh’ that does not support unset
.
(see section Portable Shell Programming).
As a general rule, shell variable names containing a lower-case letter
are safe; you can define and use these variables without worrying about
their effect on the underlying system, and without worrying about
whether the shell changes them unexpectedly. (The exception is the
shell variable status
, as described below.)
Here is a list of names that are known to cause trouble. This list is
not exhaustive, but you should be safe if you avoid the name
status
and names containing only upper-case letters and
underscores.
-
?
Not all shells correctly reset ‘$?’ after conditionals (see Limitations of Shell Builtins). Not all shells manage ‘$?’ correctly in shell functions (see section Shell Functions) or in traps (see Limitations of Shell Builtins). Not all shells reset ‘$?’ to zero after an empty command.
$ bash -c 'false; $empty; echo $?' 0 $ zsh -c 'false; $empty; echo $?' 1
-
_
-
Many shells reserve ‘$_’ for various purposes, e.g., the name of the last command executed.
-
BIN_SH
-
In Tru64, if
BIN_SH
is set toxpg4
, subsidiary invocations of the standard shell conform to Posix. -
CDPATH
-
When this variable is set it specifies a list of directories to search when invoking
cd
with a relative file name that did not start with ‘./’ or ‘../’. Posix 1003.1-2001 says that if a nonempty directory name fromCDPATH
is used successfully,cd
prints the resulting absolute file name. Unfortunately this output can break idioms like ‘abs=`cd src && pwd`’ becauseabs
receives the name twice. Also, many shells do not conform to this part of Posix; for example,zsh
prints the result only if a directory name other than ‘.’ was chosen fromCDPATH
.In practice the shells that have this problem also support
unset
, so you can work around the problem as follows:(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
You can also avoid output by ensuring that your directory name is absolute or anchored at ‘./’, as in ‘abs=`cd ./src && pwd`’.
Configure scripts use M4sh, which automatically unsets
CDPATH
if possible, so you need not worry about this problem in those scripts. -
CLICOLOR_FORCE
-
When this variable is set, some implementations of tools like
ls
attempt to add color to their output via terminal escape sequences, even when the output is not directed to a terminal, and can thus cause spurious failures in scripts. Configure scripts use M4sh, which automatically unsets this variable. -
DUALCASE
-
In the MKS shell, case statements and file name generation are case-insensitive unless
DUALCASE
is nonzero. Autoconf-generated scripts export this variable when they start up. -
ENV
-
MAIL
-
MAILPATH
-
PS1
-
PS2
-
PS4
-
These variables should not matter for shell scripts, since they are supposed to affect only interactive shells. However, at least one shell (the pre-3.0 UWIN Korn shell) gets confused about whether it is interactive, which means that (for example) a
PS1
with a side effect can unexpectedly modify ‘$?’. To work around this bug, M4sh scripts (including ‘configure’ scripts) do something like this:(unset ENV) >/dev/null 2>&1 && unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ '
(actually, there is some complication due to bugs in
unset
; see see Limitations of Shell Builtins). -
FPATH
-
The Korn shell uses
FPATH
to find shell functions, so avoidFPATH
in portable scripts.FPATH
is consulted afterPATH
, but you still need to be wary of tests that usePATH
to find whether a command exists, since they might report the wrong result ifFPATH
is also set. -
GREP_OPTIONS
-
When this variable is set, some implementations of
grep
honor these options, even if the options include direction to enable colored output via terminal escape sequences, and the result can cause spurious failures when the output is not directed to a terminal. Configure scripts use M4sh, which automatically unsets this variable. -
IFS
-
Long ago, shell scripts inherited
IFS
from the environment, but this caused many problems so modern shells ignore any environment settings forIFS
.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 reinterpret (!) 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 ‘<SPC><TAB><RET>’. The first character is especially important, as it is used to join the arguments in ‘$*’; however, note that traditional shells, but also bash-2.04, fail to adhere to this and join with a space anyway. -
LANG
-
LC_ALL
-
LC_COLLATE
-
LC_CTYPE
-
LC_MESSAGES
-
LC_MONETARY
-
LC_NUMERIC
-
LC_TIME
-
You should set all these variables to ‘C’ because so much configuration code assumes the C locale and Posix requires that locale environment variables be set to ‘C’ if the C locale is desired; ‘configure’ scripts and M4sh do that for you. Export these variables after setting them.
-
LANGUAGE
-
LANGUAGE
is not specified by Posix, but it is a GNU extension that overridesLC_ALL
in some cases, so you (or M4sh) should set it too. -
LC_ADDRESS
-
LC_IDENTIFICATION
-
LC_MEASUREMENT
-
LC_NAME
-
LC_PAPER
-
LC_TELEPHONE
-
These locale environment variables are GNU extensions. They are treated like their Posix brethren (
LC_COLLATE
, etc.) as described above. -
LINENO
-
Most modern shells provide the current line number in
LINENO
. Its value is the line number of the beginning of the current command. M4sh, and hence Autoconf, attempts to executeconfigure
with a shell that supportsLINENO
. If no such shell is available, it attempts to implementLINENO
with a Sed prepass that replaces each instance of the string$LINENO
(not followed by an alphanumeric character) with the line's number. In M4sh scripts you should executeAS_LINENO_PREPARE
so that these workarounds are included in your script; configure scripts do this automatically inAC_INIT
.You should not rely on
LINENO
withineval
or shell functions, as the behavior differs in practice. The presence of a quoted newline within simple commands can alter which line number is used as the starting point for$LINENO
substitutions within that command. Also, the possibility of the Sed prepass means that you should not rely on$LINENO
when quoted, when in here-documents, or when line continuations are used. Subshells should be OK, though. In the following example, lines 1, 9, and 14 are portable, but the other instances of$LINENO
do not have deterministic values:$ cat lineno echo 1. $LINENO echo "2. $LINENO 3. $LINENO" cat <<EOF 5. $LINENO 6. $LINENO 7. \$LINENO EOF ( echo 9. $LINENO ) eval 'echo 10. $LINENO' eval 'echo 11. $LINENO echo 12. $LINENO' echo 13. '$LINENO' echo 14. $LINENO ' 15.' $LINENO f () { echo $1 $LINENO; echo $1 $LINENO } f 18. echo 19. \ $LINENO $ bash-3.2 ./lineno 1. 1 2. 3 3. 3 5. 4 6. 4 7. $LINENO 9. 9 10. 10 11. 12 12. 13 13. $LINENO 14. 14 15. 14 18. 16 18. 17 19. 19 $ zsh-4.3.4 ./lineno 1. 1 2. 2 3. 2 5. 4 6. 4 7. $LINENO 9. 9 10. 1 11. 1 12. 2 13. $LINENO 14. 14 15. 14 18. 0 18. 1 19. 19 $ pdksh-5.2.14 ./lineno 1. 1 2. 2 3. 2 5. 4 6. 4 7. $LINENO 9. 9 10. 0 11. 0 12. 0 13. $LINENO 14. 14 15. 14 18. 16 18. 17 19. 19 $ sed '=' <lineno | > sed ' > N > s,$,-, > t loop > :loop > s,^\([0-9]*\)\(.*\)[$]LINENO\([^a-zA-Z0-9_]\),\1\2\1\3, > t loop > s,-$,, > s,^[0-9]*\n,, > ' | > sh 1. 1 2. 2 3. 3 5. 5 6. 6 7. \7 9. 9 10. 10 11. 11 12. 12 13. 13 14. 14 15. 15 18. 16 18. 17 19. 20
In particular, note that ‘config.status’ (and any other subsidiary script created by
AS_INIT_GENERATED
) might report line numbers relative to the parent script as a result of the potential Sed pass. -
NULLCMD
-
When executing the command ‘>foo’,
zsh
executes ‘$NULLCMD >foo’ unless it is operating in Bourne shell compatibility mode and thezsh
version is newer than 3.1.6-dev-18. If you are using an olderzsh
and forget to setNULLCMD
, your script might be suspended waiting for data on its standard input. -
PATH_SEPARATOR
-
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 asPATH
). You can set this variable to ‘;’ if you wantconfigure
to use ‘;’ as a separator; this might be useful if you plan to use non-Posix shells to execute files. See section File System Conventions, for more information aboutPATH_SEPARATOR
. -
PWD
-
Posix 1003.1-2001 requires that
cd
andpwd
must update thePWD
environment variable to point to the logical name of the current directory, but traditional shells do not support this. This can cause confusion if one shell instance maintainsPWD
but a subsidiary and different shell does not know aboutPWD
and executescd
; in this casePWD
points to the wrong directory. Use ‘`pwd`’ rather than ‘$PWD’. -
RANDOM
-
Many shells provide
RANDOM
, a variable that returns a different integer each time it is 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 usingset
. It is common practice to use$RANDOM
as part of a file name, but code shouldn't rely on$RANDOM
expanding to a nonempty string. -
status
-
This variable is an alias to ‘$?’ for
zsh
(at least 3.1.6), hence read-only. Do not use it.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |