28.16. Separating Commands with Semicolons
When the shell sees a semicolon
(;) on a command line, it's
treated as a command separator -- basically like pressing the
ENTER key to execute a command. When would you want to use a
semicolon instead of pressing ENTER?
It's nice when you want to execute a series of
commands, typing them all at once at a single prompt.
You'll see all of them on the same command line and
they'll be grouped together in the history list (Section 30.7).
This makes it easy to see, later, that you intended this series of
commands to be executed one after another. And you can re-execute
them all with a simple history command.
As an example, here's a series of commands that puts
a listing of the current directory into a temporary file, emails the
listing, then overwrites the previous version of the file:
$ ll > $tf-1; mail -s backup joe < $tf-1; mv $tf-1 listing
I can repeat that same command later by using a history substitution (Section 30.8) like !ll.
It's useful with sleep (Section 25.9) to run a command after a delay. The next
example shows a series of commands in a C shell alias that you might
use to print a warning and give the user a chance to abort before the
last command (exit, which ends the current shell)
is executed. Be sure to read the important note after this example:
alias bye 'echo "Type CTRL-c to abort logout"; sleep 10; exit'
Note that, in C-type shells and older Bourne-type shells, pressing
your interrupt key (Section 24.10) -- like CTRL-c -- will stop execution
of all jobs on the current command line. The alias above works in
shells like that. But in some shells, like bash2,
interrupting a command in a string
of commands separated by semicolons will affect only that single
command. So I couldn't rewrite the alias above for
bash2 because, if I pressed CTRL-c while the
sleep command was executing, that would simply
abort sleep -- and proceed to run
exit, which would log me out immediately!
If you're running a
series of commands that take some time to complete, you can type all
the commands at once and leave them to run unattended. For example, I
have little shell scripts named nup and
ndown (Section 24.22) (which run
/sbin/ifup and /sbin/ifdown,
respectively) to start and disable the
network. On a
system with a dialup modem and a long file transfer to perform,
it's nice to be able to type a series of commands
that bring up the network, do a couple of file transfers, then bring
down the network. I can type this string, go about my business
somewhere else, and come back later:
After nup returns, the network is up (the modem
has connected). So the shell runs ptbk (Section 38.9) to make a
backup of my work on this book. Next, getmail gets
my email (it basically runs fetchmail). When
getmail finishes, ndown hangs
up the modem. This can take several minutes from start to finish, but
the shell manages it all while I do something else. (If I
didn't have a windowing system with multiple
xterms, I could have put that string of commands
into a subshell (Section 43.7) in the background (Section 23.2).)
This is one place that a GUI interface for network control really
loses to command-line utilities and the shell.
Two related operators, && and
|| (Section 35.14), work like a semicolon,
but they only execute the next command if the previous one succeeded
or failed, respectively.
Copyright © 2003 O'Reilly & Associates. All rights reserved.