Shell and environment variables:
The shell maintains a list of variables, each of which has as value a
list of zero or more words. The values of shell variables can be displayed and changed with the set and unset commands. The system maintains its own list of `environment' variables. These can be displayed and changed with printenv, setenv and unsetenv.
(+) Variables may be made read-only with `set -r' (q.v.) Read-only
variables may not be modified or unset; attempting to do so will cause
an error. Once made read-only, a variable cannot be made writable, so
`set -r' should be used with caution. Environment variables cannot be
made read-only.
Some variables are set by the shell or referred to by it. For
instance, the argv variable is an image of the shell's argument list,
and words of this variable's value are referred to in special ways.
Some of the variables referred to by the shell are toggles; the shell
does not care what their value is, only whether they are set or not.
For instance, the verbose variable is a toggle which causes command
input to be echoed. The -v command line option sets this variable. Special shell variables lists all variables which are referred to by
the shell.
Other operations treat variables numerically. The `@' command permits
numeric calculations to be performed and the result assigned to a variable. Variable values are, however, always represented as (zero or
more) strings. For the purposes of numeric operations, the null string
is considered to be zero, and the second and subsequent words of multi-word values are ignored.
After the input line is aliased and parsed, and before each command is
executed, variable substitution is performed keyed by `$' characters.
This expansion can be prevented by preceding the `$' with a `\' except
within `"'s where it always occurs, and within `''s where it never occurs. Strings quoted by ``' are interpreted later (see Command substitution below) so `$' substitution does not occur there until later,
if at all. A `$' is passed unchanged if followed by a blank, tab, or
end-of-line.
Input/output redirections are recognized before variable expansion, and
are variable expanded separately. Otherwise, the command name and
entire argument list are expanded together. It is thus possible for
the first (command) word (to this point) to generate more than one
word, the first of which becomes the command name, and the rest of
which become arguments.
Unless enclosed in `"' or given the `:q' modifier the results of variable substitution may eventually be command and filename substituted.
Within `"', a variable whose value consists of multiple words expands
to a (portion of a) single word, with the words of the variable's value
separated by blanks. When the `:q' modifier is applied to a substitution the variable will expand to multiple words with each word separated by a blank and quoted to prevent later command or filename substitution.
The following metasequences are provided for introducing variable values into the shell input. Except as noted, it is an error to reference
a variable which is not set.
$name ${name} Substitutes the words of the value of variable name, each sepa- rated by a blank. Braces insulate name from following charac- ters which would otherwise be part of it. Shell variables have names consisting of up to 20 letters and digits starting with a letter. The underscore character is considered a letter. If name is not a shell variable, but is set in the environment, then that value is returned (but `:' modifiers and the other forms given below are not available in this case). $name[selector] ${name[selector]} Substitutes only the selected words from the value of name. The selector is subjected to `$' substitution and may consist of a single number or two numbers separated by a `-'. The first word of a variable's value is numbered `1'. If the first number of a range is omitted it defaults to `1'. If the last member of a range is omitted it defaults to `$#name'. The selector `*' selects all words. It is not an error for a range to be empty if the second argument is omitted or in range. $0 Substitutes the name of the file from which command input is being read. An error occurs if the name is not known. $number ${number} Equivalent to `$argv[number]'. $* Equivalent to `$argv', which is equivalent to `$argv[*]'. The `:' modifiers described under History substitution, except for `:p', can be applied to the substitutions above. More than one may be used. (+) Braces may be needed to insulate a variable substitution from a literal colon just as with History substitution (q.v.); any mod- ifiers must appear within the braces. The following substitutions can not be modified with `:' modifiers. $?name ${?name} Substitutes the string `1' if name is set, `0' if it is not. $?0 Substitutes `1' if the current input filename is known, `0' if it is not. Always `0' in interactive shells. $#name ${#name} Substitutes the number of words in name. $# Equivalent to `$#argv'. (+) $%name ${%name} Substitutes the number of characters in name. (+) $%number ${%number} Substitutes the number of characters in $argv[number]. (+) $? Equivalent to `$status'. (+) $$ Substitutes the (decimal) process number of the (parent) shell. $! Substitutes the (decimal) process number of the last background process started by this shell. (+) $_ Substitutes the command line of the last command executed. (+) $< Substitutes a line from the standard input, with no further interpretation thereafter. It can be used to read from the keyboard in a shell script. (+) While csh always quotes $<, as if it were equivalent to `$<:q', tcsh does not. Furthermore, when tcsh is waiting for a line to be typed the user may type an interrupt to interrupt the sequence into which the line is to be substituted, but csh does not allow this. The editor command expand-variables, normally bound to `^X-$', can be used to interactively expand individual variables.
Command, filename and directory stack substitution
The remaining substitutions are applied selectively to the arguments of
builtin commands. This means that portions of expressions which are
not evaluated are not subjected to these expansions. For commands
which are not internal to the shell, the command name is substituted
separately from the argument list. This occurs very late, after input-output redirection is performed, and in a child of the main shell.
Command substitution
Command substitution is indicated by a command enclosed in ``'. The
output from such a command is broken into separate words at blanks,
tabs and newlines, and null words are discarded. The output is variable and command substituted and put in place of the original string.
Command substitutions inside double quotes (`"') retain blanks and
tabs; only newlines force new words. The single final newline does not
force a new word in any case. It is thus possible for a command substitution to yield only part of a word, even if the command outputs a
complete line.
Filename substitution
If a word contains any of the characters `*', `?', `[' or `{' or begins
with the character `~' it is a candidate for filename substitution,
also known as `globbing'. This word is then regarded as a pattern
(`glob-pattern'), and replaced with an alphabetically sorted list of
file names which match the pattern.
In matching filenames, the character `.' at the beginning of a filename
or immediately following a `/', as well as the character `/' must be
matched explicitly. The character `*' matches any string of characters, including the null string. The character `?' matches any single
character. The sequence `[...]' matches any one of the characters
enclosed. Within `[...]', a pair of characters separated by `-'
matches any character lexically between the two.
(+) Some glob-patterns can be negated: The sequence `[^...]' matches
any single character not specified by the characters and/or ranges of
characters in the braces.
An entire glob-pattern can also be negated with `^':
> echo * bang crash crunch ouch > echo ^cr* bang ouch Glob-patterns which do not use `?', `*', or `[]' or which use `{}' or `~' (below) are not negated correctly.
The metanotation `a{b,c,d}e' is a shorthand for `abe ace ade'. Left-
to-right order is preserved: `/usr/source/s1/{oldls,ls}.c' expands to
`/usr/source/s1/oldls.c /usr/source/s1/ls.c'. The results of matches
are sorted separately at a low level to preserve this order:
`../{memo,*box}' might expand to `../memo ../box ../mbox'. (Note that
`memo' was not sorted with the results of matching `*box'.) It is not
an error when this construct expands to files which do not exist, but
it is possible to get an error from a command to which the expanded
list is passed. This construct may be nested. As a special case the
words `{', `}' and `{}' are passed undisturbed.
The character `~' at the beginning of a filename refers to home directories. Standing alone, i.e., `~', it expands to the invoker's home
directory as reflected in the value of the home shell variable. When
followed by a name consisting of letters, digits and `-' characters the
shell searches for a user with that name and substitutes their home
directory; thus `~ken' might expand to `/usr/ken' and `~ken/chmach' to
`/usr/ken/chmach'. If the character `~' is followed by a character
other than a letter or `/' or appears elsewhere than at the beginning
of a word, it is left undisturbed. A command like `setenv MANPATH
/usr/man:/usr/local/man:~/lib/man' does not, therefore, do home directory substitution as one might hope.
It is an error for a glob-pattern containing `*', `?', `[' or `~', with
or without `^', not to match any files. However, only one pattern in a
list of glob-patterns must match a file (so that, e.g., `rm *.a *.c
*.o' would fail only if there were no files in the current directory
ending in `.a', `.c', or `.o'), and if the nonomatch shell variable is
set a pattern (or list of patterns) which matches nothing is left
unchanged rather than causing an error.
The noglob shell variable can be set to prevent filename substitution,
and the expand-glob editor command, normally bound to `^X-*', can be
used to interactively expand individual filename substitutions.
Directory stack substitution (+)
The directory stack is a list of directories, numbered from zero, used
by the pushd, popd and dirs builtin commands (q.v.). dirs can print,
store in a file, restore and clear the directory stack at any time, and
the savedirs and dirsfile shell variables can be set to store the
directory stack automatically on logout and restore it on login. The
dirstack shell variable can be examined to see the directory stack and
set to put arbitrary directories into the directory stack.
The character `=' followed by one or more digits expands to an entry in
the directory stack. The special case `=-' expands to the last directory in the stack. For example,
> dirs -v 0 /usr/bin 1 /usr/spool/uucp 2 /usr/accts/sys > echo =1 /usr/spool/uucp > echo =0/calendar /usr/bin/calendar > echo =- /usr/accts/sys
The noglob and nonomatch shell variables and the expand-glob editor
command apply to directory stack as well as filename substitutions.
Other substitutions (+)
There are several more transformations involving filenames, not strictly related to the above but mentioned here for completeness. Any filename may be expanded to a full path when the symlinks variable
(q.v.) is set to `expand'. Quoting prevents this expansion, and the normalize-path editor command does it on demand. The normalize-command editor command expands commands in PATH into full paths on demand.
Finally, cd and pushd interpret `-' as the old working directory
(equivalent to the shell variable owd). This is not a substitution at
all, but an abbreviation recognized by only those commands. Nonetheless, it too can be prevented by quoting.
Related:
OS X Syntax
List of all Environment variables
env - List or Set environment variables