Basic variable definition
Traditionally, shell variables are declared, defined and initialized at the same time. This is done similarly to other programming languages, with the variable name on the left and the value on the right.
FOO=bar
Note that no spaces are allowed between the variable, the =
and
the value. The following do not parse as you would expect.
FOO= bar # executes bar with FOO set to the empty string
FOO =bar # executes FOO with =bar as the first argument
FOO = bar # executes FOO with = and bar as the first and second arguments
If the value you want to set the variable to contains spaces, you must enclose it in quotes like this.
FOO="bar baz"
Basic variable interpolation
The most common use for setting a variable is interpolation into another
command. The following command prints the contents of the variable
FOO
to your terminal, which would be bar baz
if it was set like the
previous section.
$ echo $FOO
bar baz
It is also possible to interpolate in a variable assignment.
$ FOO="$FOO qux "
$ echo $FOO
bar baz qux
If you want to interpolate a variable with a string which has alphanumeric characters after the interpolation, you need to use an alternative syntax.
$ echo $FOO7
$ echo ${FOO}7
bar baz qux 7
Special variables
There are a large number of special variables, which will have been pre-defined by your shell. Some of which may be modified to alter your shell's behaviour.
I'm not going to list them all, see your shell's documentation for that, but I'm going to describe the 3 most commonly used from the command line.
$?
$?
is the return code of the last program that was executed. This is
useful if a command produces no output, and you don't know if that is
a good thing or a bad thing.
It will be 0 if a command succeeded.
$ true # true always succeeds
$ echo $?
0
It will not be 0 if the command failed.
$ false # false always fails
$ echo $?
1
PS1
PS1
is the specification of how your shell will display its prompt.
$ PS1="% "
% echo My prompt is $PS1
My prompt is %
This does not need to be a fixed string, your shell will provide a formatting language, and support embedding of commands. As usual, see the documentation for more details.
PATH
PATH
is not specific to your shell, but the most common way of
interacting with it is through a shell.
It is a colon separated list of paths to directories that contain executables.
% echo $PATH
/usr/local/bin:/usr/bin:/bin
When you run a command without specifying a full path to the executable
it will use PATH
to find it, using directories specified from left
to right.
You can alter it like other variables to allow other executables to be found.
% cat ~/bin/my-command
#!/bin/sh
echo "Hello World"
% PATH="$HOME/bin:$PATH"
% my-command
Hello World
Scopes
There are 3 classes of scopes in most shells.
Global variables
FOO is a global variable, this is the default
Exported (environment) variables (if you alter PATH or export FOO)
These will be inherited by processes you execute. Any variables that were exported to you will be inherited, so you may alter the
PATH
for a subshell.You can also export FOO to a subshell with the
export
command.% sh $ echo FOO is $FOO FOO is $ exit % export FOO % sh $ echo FOO is $FOO FOO is bar baz qux
You can only unexport a variable by unsetting it, then re-setting it.
% unset FOO % FOO="bar baz qux " % echo $FOO bar baz qux % sh $ echo FOO is $FOO FOO is
Local variables (not basic shell)
Local variables are only valid inside functions. These allow a variable to be re-used across functions, and is one requirement to being able to write recursive functions.
% func () { local FOO=zxc; } % func % echo $FOO bar baz qux
Operations on variables
As shown previously, it is possible to append to a variable by
interpolating, however this requires typing out the variable twice.
Shell also supports an append operator in the form of +=
:
% FOO+=asdf
% echo $FOO
foo bar bas asdf
There are also more advanced interpolation operations, these only work with the
braced form of interpolation (${FOO}
). For a list of all of them, see the
Parameter Expansion section of the documentation.
Default value
If you want to interpolate a variable, which may not have been set, but you have a sensible default.
% unset FOO
% echo $FOO
% echo ${FOO-bar}
bar
This is terser, but less readable than doing the following.
if [ -z "$FOO" ]; then
echo bar
else
echo "$FOO"
fi
Suffix and prefix stripping
It can be convenient to remove a portion of a string, such as removing the file extension of a file,
% FOO=bar
% echo ${FOO%r}
ba
These is also a prefix strip using the #
character instead of the %
.
% echo ${FOO#b}
ar
It may help to think that the %
looks like an s, hence suffix.
Decompress directory example
As an example of combining some things that have been learned, here is a shell function that decompresses all gzipped files in a directory.
If a directory is not specified, it uses the current directory.
decompress() {
for gzipped in "${1-.}"/*.gz # Use current dir if not specified
do
gunzip -c "$gzipped" >"${gzipped%.gz}" # Strip .gz from path
done
}