Serial execution
Statements and statement lists
Parenthesis
Control structures
See also
This chapter outlines the various structures provided for connecting statements together: describing serial relationships, conditional execution, iteration and how procedures are defined and used.
As we’ve seen already, commands typed on successive lines are executed serially, one after the other. Writing several commands on one line with semicolons between them does the same thing.
The semicolon is not passed to the application you invoke. If you really do want to pass a semicolon, you have to escape it or put it inside quotes.
A non-zero return code is not normally considered an error: regardless of the return code from any particular command, serial execution continues. We can demonstrate this with the rcode utility in the Samples directory which prints, then exits with the return code value you pass it on the command line. This example also shows how you can retrieve the return code of the last child process by referring to the builtin status variable.
It’s also possible to describe a conditional serial relationship. If statements are joined by &&, the second one is executed only if the return code from the first one is 0, i.e., if the first statement succeeds. If statements are joined by ||, the second is executed only if the first one fails, i.e., returns a non-zero return code.
I/O redirection and statement connections are recognized according to a precedence. Just as in expressions, where * is done before +, statements are parsed so that some things are done before others. I/O redirection comes before piping which comes before conditional execution which comes before serializing with semicolons. For example:
The shell makes a special distinction between individual statements, no matter how complex, and lists of statements typed on separate lines or separated by semicolons.
Here’s an example using the time command, which runs a statement and prints out the hours, minutes and seconds it took. time expects a single statement as a operand; if you type a semicolon, the time command (together with its operand) becomes just one statement in the list.
There are two ways to group a list of statements together to make them act like a single statement. The simplest way is with parenthesis, which work the way they would in an expression: even if the operator inside the parentheses are of lower precedence, they’re done first.
A parenthesized group gets its own copy of the current directory and disk. This makes it convenient to change directories inside the group and go do something without having to change back afterward.
The actual implementation uses the directory stack mechanism: at entry to the group, the current directory is pushed onto the directory stack and at exit, the top entry is popped.
The more general way of connecting statements together is with control structures, discussed in the next several chapters. Control structions provide ways of describing conditional or iterative execution and for adding new vocabulary to the language using procedures. You can use a control structure anywhere a statement is allowed.
The language is completely recursive: control structures can be nested inside control structures, etc. A statement can be arbitrarily complex. Here’s an example timing a statement that turns out to be a for loop piped to a wc and inside the for loop ...
Basic statements
Statement relationships
I/O redirection
Condition testing
Iteration
Procedures
Sample scripts
Order of evaluation
Tutorial: if and switch
Tutorial: foreach, for, while and repeat
Tutorial: Procedures
Tutorial: Scripts
Tutorial: Labels and gotos