Next: Limitations of Builtins, Previous: Slashes, Up: Portable Shell
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 (see Limitations of Builtins) and a fallback value is needed.
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.
_
BIN_SH
xpg4
, subsidiary invocations of
the standard shell conform to Posix.
Autoconf-generated scripts export this variable when they start up.
CDPATH
cd
with a relative file name that did not start
with ‘./’ or ‘../’. Posix
1003.1-2001 says that if a nonempty directory name from CDPATH
is used successfully, cd
prints the resulting absolute
file name. Unfortunately this output can break idioms like
‘abs=`cd src && pwd`’ because abs
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 from CDPATH.
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`’.
Autoconf-generated scripts automatically unset CDPATH if
possible, so you need not worry about this problem in those scripts.
DUALCASE
ENV
MAIL
MAILPATH
PS1
PS2
PS4
(unset ENV) >/dev/null 2>&1 && unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ '
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 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
LANGUAGE
LC_ADDRESS
LC_IDENTIFICATION
LC_MEASUREMENT
LC_NAME
LC_PAPER
LC_TELEPHONE
LINENO
LINENO
.
Its value is the line number of the beginning of the current command.
Autoconf attempts to execute configure with a shell that
supports LINENO
.
If no such shell is available, it attempts to implement LINENO
with a Sed prepass that replaces 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,$,-, > 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 3. 3 4. 4 6. 6 7. 7 8. 8 9. 9 10. 10
NULLCMD
PATH_SEPARATOR
PATH_SEPARATOR
.
PWD
RANDOM
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 using set. 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
zsh
(at least 3.1.6),
hence read-only. Do not use it.