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:
$ nup;ptbk;getmail;ndown
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.
-- JP
Copyright © 2003 O'Reilly & Associates. All rights reserved.