User Tools

Site Tools


advanced_shell_scripting

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
advanced_shell_scripting [2018/12/08 12:49] – created 0.0.0.0advanced_shell_scripting [2019/01/30 11:32] (current) – external edit 127.0.0.1
Line 1: Line 1:
-====== Advanced_shell_scripting ====== +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
- +
-<!DOCTYPE HTML PUBLIC "-<nowiki>//</nowiki>W3C<nowiki>//</nowiki>DTD HTML 4.0 Transitional<nowiki>//</nowiki>EN">+
 <html> <html>
 <head> <head>
Line 13: Line 11:
 </head> </head>
 <body bgcolor=WHITE> <body bgcolor=WHITE>
-<h1 align=CENTER>Unix shell scripting with ksh/bash</h1> +<h1 align=CENTER>Unix shell scripting with ksh/bash====== 
-<h3 align=CENTER> Course Handout: (last update Thursday, 22-Mar-2012 12:43:56 EDT) </h3>+<h3 align=CENTER> Course Handout: (last update Thursday, 22-Mar-2012 12:43:56 EDT) ====
  
 <br> <br>
Line 25: Line 23:
  
 <p align=RIGHT ><font size=-1></font></P> <p align=RIGHT ><font size=-1></font></P>
-<font color=DARKBLUE><h1>UNIX shell scripting with ksh/bash</H1></font>+<font color=DARKBLUE>======UNIX shell scripting with ksh/bash</H1></font>
  
-<h3> The goals of this class are to enable you to:</h3>+==== The goals of this class are to enable you to:====
  
 <UL TYPE=DISC> <UL TYPE=DISC>
Line 50: Line 48:
 (<a href="http://www.FreeBSD.org/cgi/man.cgi?query=sh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sh</code></b></font></a>)<BR> (<a href="http://www.FreeBSD.org/cgi/man.cgi?query=sh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sh</code></b></font></a>)<BR>
 Output from commands is shown <TT>like this</TT>; Output from commands is shown <TT>like this</TT>;
-optional items are <I>[[|in brackets ]]</I>.+optional items are <I>[[ in brackets ]]</I>.
 <P> <P>
 Some descriptions in these notes have more detail available, Some descriptions in these notes have more detail available,
Line 61: Line 59:
 <HR> <HR>
 <SMALL> <SMALL>
-Permission is granted to download and use these notes and example scripts, as long as +Permission is granted to download and use these notes and example scripts, as long as
 all copyright notices are kept intact.  Some of the examples are taken from texts all copyright notices are kept intact.  Some of the examples are taken from texts
 or online resources which have granted permission to redistribute. or online resources which have granted permission to redistribute.
Line 68: Line 66:
 <SMALL> <SMALL>
 These notes are updated from time to time.  The "development" These notes are updated from time to time.  The "development"
-set of notes are +set of notes are
 <A HREF="http://northstar-www.dartmouth.edu/~richard/classes/ksh" TARGET=_top> http://northstar-www.dartmouth.edu/~richard/classes/ksh </A> <A HREF="http://northstar-www.dartmouth.edu/~richard/classes/ksh" TARGET=_top> http://northstar-www.dartmouth.edu/~richard/classes/ksh </A>
 (Dartmouth only) (Dartmouth only)
Line 75: Line 73:
 Richard Brittain, Dartmouth College Computing Services. Richard Brittain, Dartmouth College Computing Services.
 <BR> <BR>
-&copy; 2003,2004,2010 Dartmouth College. +&copy; 2003,2004,2010 Dartmouth College.
  
 <BR> <BR>
Line 135: Line 133:
  
 <p align=RIGHT class="newpage"><font size=-1>(1)</font></P> <p align=RIGHT class="newpage"><font size=-1>(1)</font></P>
-<font color=DARKBLUE><h1>What is a Shell Script</H1></font>+<font color=DARKBLUE>======What is a Shell Script</H1></font>
  
 <UL> <UL>
Line 194: Line 192:
  
 <p align=RIGHT class="newpage"><font size=-1>(2)</font></P> <p align=RIGHT class="newpage"><font size=-1>(2)</font></P>
-<font color=DARKBLUE><h1>Why use Shell Scripts</H1></font>+<font color=DARKBLUE>======Why use Shell Scripts</H1></font>
  
 <UL> <UL>
Line 201: Line 199:
 <LI>Generalize a sequence of operations on one set of data, into a procedure that can be <LI>Generalize a sequence of operations on one set of data, into a procedure that can be
 applied to any similar set of data. applied to any similar set of data.
-<blockquote><small>  +<blockquote><small>
  
 (e.g. (e.g.
Line 215: Line 213:
 <LI>Wrap programs over which you have no control inside an environment that you can control. <LI>Wrap programs over which you have no control inside an environment that you can control.
 <blockquote><small> <blockquote><small>
-e.g. set environment variables, switch to a special directory, create or select a configuration file, +e.g. set environment variables, switch to a special directory, create or select a configuration file,
 redirect output, log usage, and then run the program. redirect output, log usage, and then run the program.
 </small></blockquote> </small></blockquote>
Line 224: Line 222:
 <LI>Rapid prototyping (but avoid letting prototypes become production) <LI>Rapid prototyping (but avoid letting prototypes become production)
 </UL> </UL>
-<h2>Typical uses</h2>+=====Typical uses=====
  
 <UL> <UL>
Line 233: Line 231:
 <P> <P>
 <LI>Application package installation tools <LI>Application package installation tools
-<blockquote><small> +<blockquote><small>
 Other tools may create fancier installers (e.g. tcl/tk), but can not be assumed to be installed already.  Shell scripts are used because they are very portable.  Some software comes with a complete installation of the tool it wants to use Other tools may create fancier installers (e.g. tcl/tk), but can not be assumed to be installed already.  Shell scripts are used because they are very portable.  Some software comes with a complete installation of the tool it wants to use
 (tcl/tk/python) in order to be self contained, but this leads to software bloat. (tcl/tk/python) in order to be self contained, but this leads to software bloat.
-</small></blockquote> +</small></blockquote>
  
 <P> <P>
Line 243: Line 241:
 <P> <P>
  
-<LI>Any user needing to automate the process of setting up and running commercial applications, +<LI>Any user needing to automate the process of setting up and running commercial applications,
 or their own code. or their own code.
 </UL> </UL>
Line 256: Line 254:
  
 <p align=RIGHT class="newpage"><font size=-1>(3)</font></P> <p align=RIGHT class="newpage"><font size=-1>(3)</font></P>
-<font color=DARKBLUE><h1>History of Shells</H1></font>+<font color=DARKBLUE>======History of Shells</H1></font>
  
 <DL> <DL>
Line 266: Line 264:
 <P> <P>
 <DT><FONT COLOR="maroon"><a href="http://www.FreeBSD.org/cgi/man.cgi?query=csh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>csh</code></b></font></a> <DT><FONT COLOR="maroon"><a href="http://www.FreeBSD.org/cgi/man.cgi?query=csh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>csh</code></b></font></a>
-<DD>The "C" shell.  (Bill Joy, at Berkeley).  +<DD>The "C" shell.  (Bill Joy, at Berkeley).
 Many things in common Many things in common
 with the Bourne shell, but many enhancements to improve interactive use.  The internal with the Bourne shell, but many enhancements to improve interactive use.  The internal
-commands used only in scripts are <STRONG>very</STRONG> different from "sh", and +commands used only in scripts are <STRONG>very</STRONG> different from "sh", and
 similar (by design) to the "C" language syntax. similar (by design) to the "C" language syntax.
 </FONT> </FONT>
Line 278: Line 276:
 <a href="http://www.FreeBSD.org/cgi/man.cgi?query=tcsh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>tcsh</code></b></font></a> <a href="http://www.FreeBSD.org/cgi/man.cgi?query=tcsh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>tcsh</code></b></font></a>
 <DD>The "TC" shell.  Freely available and based on "csh". <DD>The "TC" shell.  Freely available and based on "csh".
-It has many additional features to make interactive use more convenient.  +It has many additional features to make interactive use more convenient.
 <blockquote><small> <blockquote><small>
 We use it as the default interactive shell for new accounts on all of our public systems. We use it as the default interactive shell for new accounts on all of our public systems.
 <BR> <BR>
-Not many people write scripts in [[t]]csh.   +Not many people write scripts in [[t]]csh. 
-See <A HREF="http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/">Csh Programming Considered Harmful</A> by +See <A HREF="http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/">Csh Programming Considered Harmful</A> by
 Tom Christiansen for a discussion of problems with programming csh scripts. Tom Christiansen for a discussion of problems with programming csh scripts.
 </small></blockquote> </small></blockquote>
Line 292: Line 290:
  
 <DD>The "Korn" shell, written by David Korn of AT&amp;T Bell Labs (now AT&amp;T Research). <DD>The "Korn" shell, written by David Korn of AT&amp;T Bell Labs (now AT&amp;T Research).
-Written as a major upgrade to "sh" and backwards compatible with it, but has many internal commands for the  +Written as a major upgrade to "sh" and backwards compatible with it, but has many internal commands for the 
-most frequently used functions.  It also incorporates many of the features from tcsh which enhance  +most frequently used functions.  It also incorporates many of the features from tcsh which enhance 
-interactive use (command line history recall etc.).  +interactive use (command line history recall etc.).
 <blockquote><small> <blockquote><small>
 It was slow to gain acceptance because earlier versions were encumbered by AT&amp;T licensing. It was slow to gain acceptance because earlier versions were encumbered by AT&amp;T licensing.
-This shell is now freely available on all systems, but sometimes not installed by default on "free" Unix.   +This shell is now freely available on all systems, but sometimes not installed by default on "free" Unix. 
-There are two major versions. ksh88 was the version incorporated into AT&amp;T SVR4 Unix, and may still be installed +There are two major versions. ksh88 was the version incorporated into AT&amp;T SVR4 Unix, and may still be installed
 by some of the commercial Unix vendors. ksh93 added more features, primarily for programming, and better POSIX compliance. by some of the commercial Unix vendors. ksh93 added more features, primarily for programming, and better POSIX compliance.
 </small></blockquote> </small></blockquote>
Line 305: Line 303:
 <DT>POSIX 1003.2 Shell Standard. <DT>POSIX 1003.2 Shell Standard.
 <DD>Standards committees worked over the Bourne shell and added many features of the Korn shell (ksh88) and <DD>Standards committees worked over the Bourne shell and added many features of the Korn shell (ksh88) and
-C shell to define a standard set of features which all compliant shells must have.  +C shell to define a standard set of features which all compliant shells must have.
 <blockquote><small> <blockquote><small>
-On most systems, /bin/sh is now a POSIX compliant shell.  +On most systems, /bin/sh is now a POSIX compliant shell.
 Korn shell and Bash are POSIX compliant, but have many features which go beyond the standard. Korn shell and Bash are POSIX compliant, but have many features which go beyond the standard.
 On Solaris, the POSIX/XPG4 commands which differ On Solaris, the POSIX/XPG4 commands which differ
Line 316: Line 314:
  
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=bash&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>bash</code></b></font></a> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=bash&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>bash</code></b></font></a>
-<DD>The "Bourne again" shell.  Written as part of the GNU/Linux Open Source effort, and the default shell for Linux and  +<DD>The "Bourne again" shell.  Written as part of the GNU/Linux Open Source effort, and the default shell for Linux and 
-Mac OS-X.  It is a functional clone of sh, with additional features to enhance interactive use, +Mac OS-X.  It is a functional clone of sh, with additional features to enhance interactive use,
 add POSIX compliance, and partial ksh compatability. add POSIX compliance, and partial ksh compatability.
  
 <P> <P>
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=zsh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>zsh</code></b></font></a> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=zsh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>zsh</code></b></font></a>
-<DD>A freeware functional clone of sh, with parts of ksh, bash and full POSIX compliance, and  +<DD>A freeware functional clone of sh, with parts of ksh, bash and full POSIX compliance, and 
-many new interactive command-line editing features.  +many new interactive command-line editing features.
 It was installed as the default shell on early MacOSX systems. It was installed as the default shell on early MacOSX systems.
 </DL> </DL>
Line 336: Line 334:
 <p align=RIGHT class="newpage"><font size=-1>(4)</font></P> <p align=RIGHT class="newpage"><font size=-1>(4)</font></P>
  
-<font color=DARKBLUE><h1>Comparison of shell features</H1></font>+<font color=DARKBLUE>======Comparison of shell features</H1></font>
  
 All the shells just listed share some common features, and the major differences in syntax All the shells just listed share some common features, and the major differences in syntax
Line 343: Line 341:
 for writing scripts. for writing scripts.
  
-<h3>Core Similarities (and recap of basic command line usage)</h3>+====Core Similarities (and recap of basic command line usage)====
 Each of these items is discussed in more detail later. Each of these items is discussed in more detail later.
 <UL> <UL>
 <LI>Parse lines by whitespace, search for external commands using <font color=DARKRED><b><code>$PATH</code></b></font>. <LI>Parse lines by whitespace, search for external commands using <font color=DARKRED><b><code>$PATH</code></b></font>.
 <LI>Can run a shell script using <font color=DARKRED><b><code>shellname scriptfile</code></b></font>, or run a single <LI>Can run a shell script using <font color=DARKRED><b><code>shellname scriptfile</code></b></font>, or run a single
 +<code>
     command using <font color=DARKRED><b><code>shellname -c "command"</code></b></font>     command using <font color=DARKRED><b><code>shellname -c "command"</code></b></font>
 +</code>
 <LI>Pass expanded command line arguments to programs; get exit status back. <LI>Pass expanded command line arguments to programs; get exit status back.
  
Line 358: Line 358:
 <LI>A few internal functions (<a href="http://www.FreeBSD.org/cgi/man.cgi?query=cd&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>cd</code></b></font></a>) <LI>A few internal functions (<a href="http://www.FreeBSD.org/cgi/man.cgi?query=cd&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>cd</code></b></font></a>)
 <LI>Backgrounding commands with <font color=DARKRED><b><code>&</code></b></font> <LI>Backgrounding commands with <font color=DARKRED><b><code>&</code></b></font>
-<LI>Quoting rules: "double quotes" protect most things, but allow <font color=DARKRED><b><code>$var</code></b></font> interpretation; +<LI>Quoting rules: "double quotes" protect most things, but allow <font color=DARKRED><b><code>$var</code></b></font> interpretation;
 'single quotes' protect all metacharacters from interpretation. 'single quotes' protect all metacharacters from interpretation.
  
Line 369: Line 369:
  
 <LI>Conditional execution using <font color=DARKRED><b><code>&amp;&amp;</code></b></font> and <font color=DARKRED><b><code>||</code></b></font> <LI>Conditional execution using <font color=DARKRED><b><code>&amp;&amp;</code></b></font> and <font color=DARKRED><b><code>||</code></b></font>
-<LI>Line continuation with "<font color=DARKRED><b><code>\</code></b></font>"+<LI>Line continuation with "<font color=DARKRED><b><code>\\</code></b></font>"
 </UL> </UL>
  
-<h3>Principal Differences</h3>+====Principal Differences====
 between sh (+derivitives), and csh (+derivitives). between sh (+derivitives), and csh (+derivitives).
 <UL> <UL>
Line 396: Line 396:
  
 <p align=RIGHT class="newpage"><font size=-1>(5)</font></P> <p align=RIGHT class="newpage"><font size=-1>(5)</font></P>
-<font color=DARKBLUE><h1>Other Scripting Languages</H1></font>+<font color=DARKBLUE>======Other Scripting Languages</H1></font>
  
 There are many other programs which read a file of commands and carry out There are many other programs which read a file of commands and carry out
Line 409: Line 409:
 <LI>what similar code already exists <LI>what similar code already exists
 <LI>what you are most familiar with and can use most efficiently. <LI>what you are most familiar with and can use most efficiently.
-Your time is always more expensive than computer cycles.  +Your time is always more expensive than computer cycles.
  
 </UL> </UL>
Line 416: Line 416:
 <LI><a href="http://www.FreeBSD.org/cgi/man.cgi?query=awk&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>awk</code></b></font></a> <LI><a href="http://www.FreeBSD.org/cgi/man.cgi?query=awk&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>awk</code></b></font></a>
 <blockquote><small> <blockquote><small>
-A pattern matching and data (text and numeric) manipulation tool.  Predates perl.  Installed on +A pattern matching and data (text and numeric) manipulation tool.  Predates perl.  Installed on
 all Unix systems.  Often used in combination with shell scripts. all Unix systems.  Often used in combination with shell scripts.
 </small></blockquote> </small></blockquote>
Line 424: Line 424:
 The most used scripting language for Web CGI applications and system administration tasks.  Perl The most used scripting language for Web CGI applications and system administration tasks.  Perl
 is harder to learn, and is uusually installed by default now. is harder to learn, and is uusually installed by default now.
-It is more efficient and has an enormous library of functions available.  You could use Perl for +It is more efficient and has an enormous library of functions available.  You could use Perl for
 almost all scripting tasks, but the syntax is very different to the shell command line almost all scripting tasks, but the syntax is very different to the shell command line
  
Line 436: Line 436:
 <LI><a href="http://www.FreeBSD.org/cgi/man.cgi?query=tcl&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>tcl</code></b></font></a>/<a href="http://www.FreeBSD.org/cgi/man.cgi?query=tk&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>tk</code></b></font></a> <LI><a href="http://www.FreeBSD.org/cgi/man.cgi?query=tcl&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>tcl</code></b></font></a>/<a href="http://www.FreeBSD.org/cgi/man.cgi?query=tk&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>tk</code></b></font></a>
 <blockquote><small> <blockquote><small>
-Tool Command Language.  Another general purpose scripting language.  The "tk" component is a +Tool Command Language.  Another general purpose scripting language.  The "tk" component is a
 scripted interface to standard X-windows graphical components, so the combination is often used scripted interface to standard X-windows graphical components, so the combination is often used
-to create graphical user interfaces.  +to create graphical user interfaces.
 <P> <P>
-Ksh93 can be extended by linking to shared libraries providing additional internal commands.  One example +Ksh93 can be extended by linking to shared libraries providing additional internal commands.  One example
 of an extended shell is of an extended shell is
 <A HREF="http://www.cs.princeton.edu/~jlk/tksh/"" TARGET="_blank"><font color=DARKRED><b><code>tksh</code></b></font></A> <A HREF="http://www.cs.princeton.edu/~jlk/tksh/"" TARGET="_blank"><font color=DARKRED><b><code>tksh</code></b></font></A>
  
-which incorporates Tcl/Tk with ksh and allows generation of +which incorporates Tcl/Tk with ksh and allows generation of
 scripts using both languages.  It can be used for prototyping GUI applications. scripts using both languages.  It can be used for prototyping GUI applications.
 </small></blockquote> </small></blockquote>
Line 457: Line 457:
  
 <p align=RIGHT class="newpage"><font size=-1>(6)</font></P> <p align=RIGHT class="newpage"><font size=-1>(6)</font></P>
-<font color=DARKBLUE><h1>ksh/bash vs sh</H1></font>+<font color=DARKBLUE>======ksh/bash vs sh</H1></font>
  
 Ksh and bash are both supersets of sh.  For maximum portability, even to very old Ksh and bash are both supersets of sh.  For maximum portability, even to very old
Line 466: Line 466:
  
 <blockquote><small> <blockquote><small>
-The philosophy of separate Unix tools each performing a single +The philosophy of separate Unix tools each performing a single
 operation was followed closely by the designers of the original shell, so it operation was followed closely by the designers of the original shell, so it
 had very few internal commands and had very few internal commands and
 used external tools for very trivial operations used external tools for very trivial operations
-(like <font color=DARKRED><b><code>echo</code></b></font> and <font color=DARKRED><b><code>[[</code></b></font>).Ksh and bash internally+(like <font color=DARKRED><b><code>echo</code></b></font> and <font color=DARKRED><b><code>[[</code></b></font>).  Ksh and bash internally
 performs many of the basic string and numeric manipulations and conditional tests. Occasional problems performs many of the basic string and numeric manipulations and conditional tests. Occasional problems
 arise because the internal versions of some commands like <font color=DARKRED><b><code>echo</code></b></font> are not fully compatible with arise because the internal versions of some commands like <font color=DARKRED><b><code>echo</code></b></font> are not fully compatible with
Line 476: Line 476:
 <P> <P>
 The action taken every time a shell needs to run an external program is to locate the program The action taken every time a shell needs to run an external program is to locate the program
-(via $PATH), <font color=DARKRED><b><code>fork()</code></b></font>, which creates a second copy of the shell, +(via $PATH), <font color=DARKRED><b><code>fork()</code></b></font>, which creates a second copy of the shell,
 adjust the standard input/output for the adjust the standard input/output for the
-external program, and <font color=DARKRED><b><code>exec()</code></b></font>, which replaces the second shell with the external program.  +external program, and <font color=DARKRED><b><code>exec()</code></b></font>, which replaces the second shell with the external program.
 This process is computationally expensive (relatively), so when the script does something trivial This process is computationally expensive (relatively), so when the script does something trivial
 many times over in a loop, it saves a lot of time if the function is handled internally. many times over in a loop, it saves a lot of time if the function is handled internally.
Line 484: Line 484:
  
 <P> <P>
-If you follow textbooks on Bourne shell programming, all of the advice should apply no matter +If you follow textbooks on Bourne shell programming, all of the advice should apply no matter
 which of the Bourne-derived shells you use.  Unfortunately, many vendors have added features over the years which of the Bourne-derived shells you use.  Unfortunately, many vendors have added features over the years
 and achieving complete portability can be a challenge.  Explicitly writing for ksh (or bash) and insisting and achieving complete portability can be a challenge.  Explicitly writing for ksh (or bash) and insisting
Line 500: Line 500:
  
 <p align=RIGHT class="newpage"><font size=-1>(7)</font></P> <p align=RIGHT class="newpage"><font size=-1>(7)</font></P>
-<font color=DARKBLUE><h1>Basic sh script syntax</H1></font>+<font color=DARKBLUE>======Basic sh script syntax</H1></font>
  
 The most basic shell script is a list of commands exactly as could be The most basic shell script is a list of commands exactly as could be
 typed interactively, prefaced by the <font color=DARKRED><b><code>#!</code></b></font> magic header. typed interactively, prefaced by the <font color=DARKRED><b><code>#!</code></b></font> magic header.
 All the parsing rules, filename wildcards, $PATH searches etc., which were summarized All the parsing rules, filename wildcards, $PATH searches etc., which were summarized
-above, apply.  +above, apply.
  
 <BR> <BR>
Line 514: Line 514:
 comments liberally in your scripts, as in all other forms of programming. comments liberally in your scripts, as in all other forms of programming.
 <P> <P>
-<DT><font color=DARKRED><b><code>\</code></b></font> as the last character on a line+<DT><font color=DARKRED><b><code>\\</code></b></font> as the last character on a line
 <DD>causes the following line to be logically joined before interpretation.  This allows <DD>causes the following line to be logically joined before interpretation.  This allows
 single very long commands to be entered in the script in a more readable fashion.  You can continue single very long commands to be entered in the script in a more readable fashion.  You can continue
 the line as many times as needed. the line as many times as needed.
 <blockquote><small> <blockquote><small>
-This is actually just a particular instance of <font color=DARKRED><b><code>\</code></b></font> being to <EM>escape</EM>, or remove+This is actually just a particular instance of <font color=DARKRED><b><code>\\</code></b></font> being to <EM>escape</EM>, or remove
 the special meaning from, the following character. the special meaning from, the following character.
  
Line 538: Line 538:
  
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i><b>## Some comments are bold to flag special sections</b></i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i><b>## Some comments are bold to flag special sections</b></i></font>
-<font color=GRAY>   5:</font> +<font color=GRAY>   5:</font>
 <font color=GRAY>   6:</font> <font color=DARKGREEN><i># Line numbers on the left are not part of the script.</i></font> <font color=GRAY>   6:</font> <font color=DARKGREEN><i># Line numbers on the left are not part of the script.</i></font>
 <font color=GRAY>   7:</font> <font color=DARKGREEN><i># They are just added to the HTML for reference.</i></font> <font color=GRAY>   7:</font> <font color=DARKGREEN><i># They are just added to the HTML for reference.</i></font>
  
-<font color=GRAY>   8:</font> +<font color=GRAY>   8:</font>
 <font color=GRAY>   9:</font> <font color=DARKGREEN><i># Built-in commands and keywords (e.g. print) are in blue</i></font> <font color=GRAY>   9:</font> <font color=DARKGREEN><i># Built-in commands and keywords (e.g. print) are in blue</i></font>
 <font color=GRAY>  10:</font> <font color=DARKGREEN><i># Command substitutions are purple. Variables are black</i></font> <font color=GRAY>  10:</font> <font color=DARKGREEN><i># Command substitutions are purple. Variables are black</i></font>
 <font color=GRAY>  11:</font> <font color=DARKBLUE>print </font>"Disk usage summary for <font color=BLACK>$USER</font> on `<font color=PURPLE>date</font>`" <font color=GRAY>  11:</font> <font color=DARKBLUE>print </font>"Disk usage summary for <font color=BLACK>$USER</font> on `<font color=PURPLE>date</font>`"
  
-<font color=GRAY>  12:</font> +<font color=GRAY>  12:</font>
 <font color=GRAY>  13:</font> <font color=DARKGREEN><i># Everything else is red - mostly that is external </i></font> <font color=GRAY>  13:</font> <font color=DARKGREEN><i># Everything else is red - mostly that is external </i></font>
 <font color=GRAY>  14:</font> <font color=DARKGREEN><i># commands, and the arguments to all of the commands.</i></font> <font color=GRAY>  14:</font> <font color=DARKGREEN><i># commands, and the arguments to all of the commands.</i></font>
Line 558: Line 558:
  
 <font color=GRAY>  20:</font> <font color=DARKBLUE>print </font>Disk space usage <font color=GRAY>  20:</font> <font color=DARKBLUE>print </font>Disk space usage
-<font color=GRAY>  21:</font> du -k +<font color=GRAY>  21:</font> du -k
 <font color=GRAY>  22:</font> <font color=DARKBLUE>exit </font>0 <font color=GRAY>  22:</font> <font color=DARKBLUE>exit </font>0
 </font></code> </font></code>
Line 564: Line 564:
 </SMALL></BLOCKQUOTE> </SMALL></BLOCKQUOTE>
  
-<h2>Exit status</h2>+=====Exit status=====
  
-Every command (program) has a <EM>value</EM> or <EM>exit status</EM>  +Every command (program) has a <EM>value</EM> or <EM>exit status</EM> 
-which it returns to the calling program.  This +which it returns to the calling program.  This
 is separate from any output generated.   The exit status of a shell script can be explicitly set using is separate from any output generated.   The exit status of a shell script can be explicitly set using
 <a href="http://www.FreeBSD.org/cgi/man.cgi?query=exit&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>exit</code></b></font></a> <font color=DARKRED><b><code>N</code></b></font>, or it defaults to the value of the last command run. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=exit&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>exit</code></b></font></a> <font color=DARKRED><b><code>N</code></b></font>, or it defaults to the value of the last command run.
Line 574: Line 574:
 any other value indicates a problem.  Think of it as only one way for everything to any other value indicates a problem.  Think of it as only one way for everything to
 work, but many possible ways to fail.  If the command was terminated by a signal, the value is 128 plus work, but many possible ways to fail.  If the command was terminated by a signal, the value is 128 plus
-the signal value.  +the signal value.
  
 </small></blockquote> </small></blockquote>
Line 586: Line 586:
  
 <p align=RIGHT class="newpage"><font size=-1>(8)</font></P> <p align=RIGHT class="newpage"><font size=-1>(8)</font></P>
-<font color=DARKBLUE><h1>Filename Wildcards</H1></font>+<font color=DARKBLUE>======Filename Wildcards</H1></font>
  
 The following characters are interpreted by the shell as filename wildcards, and The following characters are interpreted by the shell as filename wildcards, and
Line 602: Line 602:
 <DT><font color=DARKRED><b><code>?</code></b></font> <DT><font color=DARKRED><b><code>?</code></b></font>
 <DD>Match any single character <DD>Match any single character
-<DT><font color=DARKRED><b><code>[...]]</code></b></font>+<DT><font color=DARKRED><b><code>[[...]]</code></b></font>
 <DD>Match any single character from the bracketed set.  A range of characters can be specified <DD>Match any single character from the bracketed set.  A range of characters can be specified
-with <font color=DARKRED><b><code>[[-  ]]</code></b></font>+with <font color=DARKRED><b><code>[[  -  ]]</code></b></font>
 <DT><font color=DARKRED><b><code>[[!...]]</code></b></font> <DT><font color=DARKRED><b><code>[[!...]]</code></b></font>
 <DD>Match any single character NOT in the bracketed set. <DD>Match any single character NOT in the bracketed set.
Line 629: Line 629:
  
 <p align=RIGHT class="newpage"><font size=-1>(9)</font></P> <p align=RIGHT class="newpage"><font size=-1>(9)</font></P>
-<font color=DARKBLUE><h1>Shell Variables</H1></font>+<font color=DARKBLUE>======Shell Variables</H1></font>
  
 Scripts are not very useful if all the commands and options and filenames are explicitly Scripts are not very useful if all the commands and options and filenames are explicitly
 coded.  By using variables, you can make a script generic and apply it to different coded.  By using variables, you can make a script generic and apply it to different
 situations.  Variable names consist of letters, numbers and underscores situations.  Variable names consist of letters, numbers and underscores
 +<code>
  ([[a-zA-Z0-9_]], cannot start with a number, and are case  ([[a-zA-Z0-9_]], cannot start with a number, and are case
 +</code>
 sensitive.  Several special variables (always uppercase names) are used by the system -- resetting these sensitive.  Several special variables (always uppercase names) are used by the system -- resetting these
 may cause unexpected behaviour.  Some special variables may be read-only. may cause unexpected behaviour.  Some special variables may be read-only.
 Using lowercase names for your own variables is safest. Using lowercase names for your own variables is safest.
 <P> <P>
-<h3>Setting and exporting variables</h3>+====Setting and exporting variables====
  
 <DL> <DL>
Line 662: Line 664:
 </DL> </DL>
  
-<h3>Using variables</h3>+====Using variables====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$srcfile</code></b></font> <DT><font color=DARKRED><b><code>$srcfile</code></b></font>
-<DD>Prefacing the variable name with <B>$</B> causes the <EM>value</EM> of the variable to +<DD>Prefacing the variable name with <B>$</B> causes the <EM>value</EM> of the variable to
 be substituted in place of the name. be substituted in place of the name.
  
 <DT><font color=DARKRED><b><code>${srcfile}</code></b></font> <DT><font color=DARKRED><b><code>${srcfile}</code></b></font>
-<DD>If the variable is not surrounded by whitespace (or other characters that can't be in a name), +<DD>If the variable is not surrounded by whitespace (or other characters that can't be in a name),
 the name must be surrounded by "{}" braces the name must be surrounded by "{}" braces
 so that the shell knows what characters you intend to be part of the name. so that the shell knows what characters you intend to be part of the name.
Line 676: Line 678:
 <PRE> <PRE>
 datafile=census2000 datafile=census2000
-  - Tries to find $datafile_part1, which doesn't exist +  -  Tries to find $datafile_part1, which doesn't exist 
-echo $datafile_part1.sas  +echo $datafile_part1.sas 
-  - This is what we intended +  -  This is what we intended 
-echo ${datafile}_part1.sas  +echo ${datafile}_part1.sas
 </PRE> </PRE>
 </DL> </DL>
  
-<h3>Conditional modifiers</h3>+====Conditional modifiers====
 There are various ways to conditionally use a variable in a command. There are various ways to conditionally use a variable in a command.
 <DL> <DL>
 <DT><font color=DARKRED><b><code>${datafile-default}</code></b></font> <DT><font color=DARKRED><b><code>${datafile-default}</code></b></font>
  
-<DD>Substitute the value of <font color=DARKRED><b><code>$datafile</code></b></font>, if it has been defined, otherwise use the string "default". This is an easy  +<DD>Substitute the value of <font color=DARKRED><b><code>$datafile</code></b></font>, if it has been defined, otherwise use the string "default". This is an easy 
-way to allow for optional variables, and have sensible defaults if they haven't been set.  If <font color=DARKRED><b><code>datafile</code></b></font> was +way to allow for optional variables, and have sensible defaults if they haven't been set.  If <font color=DARKRED><b><code>datafile</code></b></font> was
 undefined, it remains so. undefined, it remains so.
 <DT><font color=DARKRED><b><code>${datafile=default}</code></b></font> <DT><font color=DARKRED><b><code>${datafile=default}</code></b></font>
 <DD>Similar to the above, except if <font color=DARKRED><b><code>datafile</code></b></font> has not been defined, set it to the string "default". <DD>Similar to the above, except if <font color=DARKRED><b><code>datafile</code></b></font> has not been defined, set it to the string "default".
 <DT><font color=DARKRED><b><code>${datafile+default}</code></b></font> <DT><font color=DARKRED><b><code>${datafile+default}</code></b></font>
-<DD>If variable <font color=DARKRED><b><code>datafile</code></b></font> has been defined, use the string "default", otherwise use null.  In this case the +<DD>If variable <font color=DARKRED><b><code>datafile</code></b></font> has been defined, use the string "default", otherwise use null.  In this case the
 actual value <font color=DARKRED><b><code>$datafile</code></b></font> is not used. actual value <font color=DARKRED><b><code>$datafile</code></b></font> is not used.
  
Line 703: Line 705:
 Placing a colon (<B>></B>) before the operator character in these constructs has the effect of counting a Placing a colon (<B>></B>) before the operator character in these constructs has the effect of counting a
 <I>null</I> value the same as an undefined variable.  Variables may be given a null value by setting them <I>null</I> value the same as an undefined variable.  Variables may be given a null value by setting them
-to an empty string, e.g. <font color=DARKRED><b><code>datafile= </code></b></font>+to an empty string, e.g. <font color=DARKRED><b><code>datafile= </code></b></font>.
 <BR><I>Example:</I> <BR><I>Example:</I>
  
Line 712: Line 714:
 </DL> </DL>
  
-<h3>Variable assignment command prefix</h3>+====Variable assignment command prefix====
 It is possible to export a variable just for the duration of a single command using the It is possible to export a variable just for the duration of a single command using the
 syntax: syntax:
Line 724: Line 726:
  
 <p align=RIGHT class="newpage"><font size=-1>(10)</font></P> <p align=RIGHT class="newpage"><font size=-1>(10)</font></P>
-<font color=DARKBLUE><h1>Preset Shell Variables</H1></font>+<font color=DARKBLUE>======Preset Shell Variables</H1></font>
  
 Several special variables are used by the system -- you can use these, but may not be able Several special variables are used by the system -- you can use these, but may not be able
 to change them. to change them.
-The special variables use uppercase names, or punctuation characters.   +The special variables use uppercase names, or punctuation characters. 
-Some variables are set by the login process and inherited by the shell (e.g. <font color=DARKRED><b><code>$USER</code></b></font>), +Some variables are set by the login process and inherited by the shell (e.g. <font color=DARKRED><b><code>$USER</code></b></font>),
 while others are used only by the shell.  <br> while others are used only by the shell.  <br>
 Try running <font color=DARKRED><b><code>set</code></b></font> or <font color=DARKRED><b><code>env</code></b></font> <br> Try running <font color=DARKRED><b><code>set</code></b></font> or <font color=DARKRED><b><code>env</code></b></font> <br>
Line 735: Line 737:
 These are some of the more commonly used ones: These are some of the more commonly used ones:
  
-<h2>Login environment</h2>+=====Login environment=====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$USER, $LOGNAME</code></b></font> <DT><font color=DARKRED><b><code>$USER, $LOGNAME</code></b></font>
Line 748: Line 750:
 <DT><font color=DARKRED><b><code>$PAGER</code></b></font> <DT><font color=DARKRED><b><code>$PAGER</code></b></font>
 <DD>If set, this contains the name of the program which the user prefers to use for text file viewing.  Usually <DD>If set, this contains the name of the program which the user prefers to use for text file viewing.  Usually
-set to "more" or "less" or something similar.  Many programs which need to present multipage information to +set to "more" or "less" or something similar.  Many programs which need to present multipage information to
 the user will respect this setting (e.g. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=man&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>man</code></b></font></a>).  This isn't actually used by the shell itself, but the user will respect this setting (e.g. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=man&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>man</code></b></font></a>).  This isn't actually used by the shell itself, but
 shell scripts should honour it if they need to page output to the user. shell scripts should honour it if they need to page output to the user.
Line 755: Line 757:
 <DD>If set, this contains the name of the program which the user prefers to use for text file editing.  A program <DD>If set, this contains the name of the program which the user prefers to use for text file editing.  A program
 which needs to have the user manually edit a file might choose to start up this program instead of some which needs to have the user manually edit a file might choose to start up this program instead of some
-built-in default (e.g. "crontab -e" This also determines the default command-line-editing +built-in default (e.g. "crontab -e" This also determines the default command-line-editing
 behaviour in interactive shells. behaviour in interactive shells.
 </DL> </DL>
-<h2>Shell internal settings</h2>+=====Shell internal settings=====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$PWD</code></b></font> <DT><font color=DARKRED><b><code>$PWD</code></b></font>
Line 773: Line 775:
 <DT><font color=DARKRED><b><code>$IFS</code></b></font> <DT><font color=DARKRED><b><code>$IFS</code></b></font>
 <DD>Internal Field Separators: the set of characters (normally space and tab) which are used to parse <DD>Internal Field Separators: the set of characters (normally space and tab) which are used to parse
-a command line into separate arguments.  This may be set by the user for special purposes, but +a command line into separate arguments.  This may be set by the user for special purposes, but
 things get very confusing if it isn't changed back. things get very confusing if it isn't changed back.
 </DL> </DL>
-<h2>Process ID variables</h2>+=====Process ID variables=====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$$</code></b></font> (readonly) <DT><font color=DARKRED><b><code>$$</code></b></font> (readonly)
Line 786: Line 788:
 <DD>Set to the process ID of the last command started in background - useful for checking on background processes. <DD>Set to the process ID of the last command started in background - useful for checking on background processes.
 </DL> </DL>
-<h2>ksh/bash additional features</h2>+=====ksh/bash additional features=====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$SECONDS</code></b></font> (readonly) <DT><font color=DARKRED><b><code>$SECONDS</code></b></font> (readonly)
Line 806: Line 808:
  
 <p align=RIGHT class="newpage"><font size=-1>(11)</font></P> <p align=RIGHT class="newpage"><font size=-1>(11)</font></P>
-<font color=DARKBLUE><h1>Command Line (positional) arguments</H1></font>+<font color=DARKBLUE>======Command Line (positional) arguments</H1></font>
  
-To customize the behaviour of a script at run time, +To customize the behaviour of a script at run time,
 you can give it any number of arguments on the command you can give it any number of arguments on the command
 line. line.
Line 816: Line 818:
 <a href="http://www.FreeBSD.org/cgi/man.cgi?query=getopts&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>getopts</code></b></font></a> is available to help parse them. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=getopts&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>getopts</code></b></font></a> is available to help parse them.
 </small></blockquote>  The shell expands wildcards and makes variable and </small></blockquote>  The shell expands wildcards and makes variable and
-command substitutions as normal, then parses the resulting words by whitespace (actually  +command substitutions as normal, then parses the resulting words by whitespace (actually 
-special variable <font color=DARKRED><b><code>$IFS</code></b></font>), and places the resulting text strings into the +special variable <font color=DARKRED><b><code>$IFS</code></b></font>), and places the resulting text strings into the
 <EM>positional variables</EM> <EM>positional variables</EM>
 as follows: as follows:
Line 824: Line 826:
 <DT><font color=DARKRED><b><code>$0, $1, $2, ... $9</code></b></font> <DT><font color=DARKRED><b><code>$0, $1, $2, ... $9</code></b></font>
  
-<DD>The first 9 arguments are made available directly as $1-$9.  To access more than 9, use +<DD>The first 9 arguments are made available directly as $1-$9.  To access more than 9, use
 <font color=DARKRED><b><code>shift</code></b></font>, or <font color=DARKRED><b><code>$*, $@</code></b></font> The variable <font color=DARKRED><b><code>$0</code></b></font> contains the name of the <font color=DARKRED><b><code>shift</code></b></font>, or <font color=DARKRED><b><code>$*, $@</code></b></font> The variable <font color=DARKRED><b><code>$0</code></b></font> contains the name of the
 script itself. script itself.
Line 835: Line 837:
 <DD>contains the number of arguments that were set (not including $0). <DD>contains the number of arguments that were set (not including $0).
 <DT><font color=DARKRED><b><code>$*</code></b></font> <DT><font color=DARKRED><b><code>$*</code></b></font>
-<DD>contains all of the arguments in a single string, with one space separating them.  +<DD>contains all of the arguments in a single string, with one space separating them.
 <DT><font color=DARKRED><b><code>$@</code></b></font> <DT><font color=DARKRED><b><code>$@</code></b></font>
-<DD>similar to $*, but if used in quotes, it effectively quotes each argument and keeps them separate.  +<DD>similar to $*, but if used in quotes, it effectively quotes each argument and keeps them separate.
 If any argument contains whitespace, the distinction is important. If any argument contains whitespace, the distinction is important.
 </DL> </DL>
Line 857: Line 859:
 <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Check positional argument handling</i></font> <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Check positional argument handling</i></font>
 <font color=GRAY>   4:</font> <font color=DARKBLUE>echo </font>"Number of arguments: $#" <font color=GRAY>   4:</font> <font color=DARKBLUE>echo </font>"Number of arguments: $#"
-<font color=GRAY>   5:</font> <font color=DARKBLUE>echo </font>"\<font color=BLACK>$0</font> = <font color=BLACK>$0</font>"+<font color=GRAY>   5:</font> <font color=DARKBLUE>echo </font>"\\<font color=BLACK>$0</font> = <font color=BLACK>$0</font>"
  
-<font color=GRAY>   6:</font>  +<font color=GRAY>   6:</font> 
-<font color=GRAY>   7:</font> <font color=DARKBLUE>echo </font>"Loop over \<font color=BLACK>$*</font>"+<font color=GRAY>   7:</font> <font color=DARKBLUE>echo </font>"Loop over \\<font color=BLACK>$*</font>"
 <font color=GRAY>   8:</font> <font color=DARKBLUE>for </font>a in <font color=BLACK>$*</font>; <font color=DARKBLUE>do</font> <font color=GRAY>   8:</font> <font color=DARKBLUE>for </font>a in <font color=BLACK>$*</font>; <font color=DARKBLUE>do</font>
  
-<font color=GRAY>   9:</font>    <font color=DARKBLUE>echo </font>\"<font color=BLACK>$a</font>\"+<font color=GRAY>   9:</font>    <font color=DARKBLUE>echo </font>\\"<font color=BLACK>$a</font>\\"
 <font color=GRAY>  10:</font> <font color=DARKBLUE>done</font> <font color=GRAY>  10:</font> <font color=DARKBLUE>done</font>
-<font color=GRAY>  11:</font>  +<font color=GRAY>  11:</font> 
-<font color=GRAY>  12:</font> <font color=DARKBLUE>echo </font>"Loop over \"\<font color=BLACK>$@</font>\""+<font color=GRAY>  12:</font> <font color=DARKBLUE>echo </font>"Loop over \\"\\<font color=BLACK>$@</font>\\""
  
 <font color=GRAY>  13:</font> <font color=DARKBLUE>for </font>a in "<font color=BLACK>$@</font>"; <font color=DARKBLUE>do</font> <font color=GRAY>  13:</font> <font color=DARKBLUE>for </font>a in "<font color=BLACK>$@</font>"; <font color=DARKBLUE>do</font>
-<font color=GRAY>  14:</font>    <font color=DARKBLUE>echo </font>\"<font color=BLACK>$a</font>\"+<font color=GRAY>  14:</font>    <font color=DARKBLUE>echo </font>\\"<font color=BLACK>$a</font>\\"
 <font color=GRAY>  15:</font> <font color=DARKBLUE>done</font> <font color=GRAY>  15:</font> <font color=DARKBLUE>done</font>
  
Line 876: Line 878:
 </SMALL></BLOCKQUOTE> </SMALL></BLOCKQUOTE>
  
-<h2>Setting new positional arguments</h2>+=====Setting new positional arguments=====
  
-The <a href="http://www.FreeBSD.org/cgi/man.cgi?query=set&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>set</code></b></font></a> command, followed by a set of arguments, creates a new set of +The <a href="http://www.FreeBSD.org/cgi/man.cgi?query=set&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>set</code></b></font></a> command, followed by a set of arguments, creates a new set of
 positional arguments.  This is often used, assuming the original arguments are no longer needed, to parse positional arguments.  This is often used, assuming the original arguments are no longer needed, to parse
 a set of words (possibly using different field separators).  Arguments may be reset any number of times. a set of words (possibly using different field separators).  Arguments may be reset any number of times.
Line 909: Line 911:
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font>
  
-<font color=GRAY>   2:</font> +<font color=GRAY>   2:</font>
 <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Select a random image from the background logo collection</i></font> <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Select a random image from the background logo collection</i></font>
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i># This could be used to configure a screen saver, for example.</i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i># This could be used to configure a screen saver, for example.</i></font>
Line 915: Line 917:
  
 <font color=GRAY>   6:</font> <font color=DARKGREEN><i># This works even if the filenames contain spaces.</i></font> <font color=GRAY>   6:</font> <font color=DARKGREEN><i># This works even if the filenames contain spaces.</i></font>
-<font color=GRAY>   7:</font> +<font color=GRAY>   7:</font>
 <font color=GRAY>   8:</font> <font color=DARKGREEN><i># switch to the logos directory to avoid long paths</i></font> <font color=GRAY>   8:</font> <font color=DARKGREEN><i># switch to the logos directory to avoid long paths</i></font>
 <font color=GRAY>   9:</font> <font color=BLACK>logos=</font>/afs/northstar/common/usr/lib/X11/logos/backgrounds <font color=GRAY>   9:</font> <font color=BLACK>logos=</font>/afs/northstar/common/usr/lib/X11/logos/backgrounds
  
 <font color=GRAY>  10:</font> <font color=DARKBLUE>cd </font><font color=BLACK>$logos</font> <font color=GRAY>  10:</font> <font color=DARKBLUE>cd </font><font color=BLACK>$logos</font>
-<font color=GRAY>  11:</font> +<font color=GRAY>  11:</font>
 <font color=GRAY>  12:</font> <font color=DARKGREEN><i># '*' is a filename wildcard to match all files in the current directory</i></font> <font color=GRAY>  12:</font> <font color=DARKGREEN><i># '*' is a filename wildcard to match all files in the current directory</i></font>
 <font color=GRAY>  13:</font> set * <font color=GRAY>  13:</font> set *
  
-<font color=GRAY>  14:</font> +<font color=GRAY>  14:</font>
 <font color=GRAY>  15:</font> <font color=DARKGREEN><i># Use the syntax for arithmetic expressions.  "%" is the modulo operator</i></font> <font color=GRAY>  15:</font> <font color=DARKGREEN><i># Use the syntax for arithmetic expressions.  "%" is the modulo operator</i></font>
 <font color=GRAY>  16:</font> <font color=DARKGREEN><i># Shift arguments by a random number between 0 and the number of files</i></font> <font color=GRAY>  16:</font> <font color=DARKGREEN><i># Shift arguments by a random number between 0 and the number of files</i></font>
 <font color=GRAY>  17:</font> <font color=DARKBLUE>shift </font><font color=DARKBLUE>$((<font color=BLACK>$RANDOM</font> % $#))</font> <font color=GRAY>  17:</font> <font color=DARKBLUE>shift </font><font color=DARKBLUE>$((<font color=BLACK>$RANDOM</font> % $#))</font>
  
-<font color=GRAY>  18:</font> +<font color=GRAY>  18:</font>
 <font color=GRAY>  19:</font> <font color=DARKGREEN><i># Output the resulting first argument</i></font> <font color=GRAY>  19:</font> <font color=DARKGREEN><i># Output the resulting first argument</i></font>
 <font color=GRAY>  20:</font> <font color=DARKBLUE>echo </font>"<font color=BLACK>$logos</font>/<font color=BLACK>$1</font>" <font color=GRAY>  20:</font> <font color=DARKBLUE>echo </font>"<font color=BLACK>$logos</font>/<font color=BLACK>$1</font>"
Line 946: Line 948:
  
 <p align=RIGHT class="newpage"><font size=-1>(12)</font></P> <p align=RIGHT class="newpage"><font size=-1>(12)</font></P>
-<font color=DARKBLUE><h1>Shell options</H1></font>+<font color=DARKBLUE>======Shell options</H1></font>
  
-Startup options. <font color=DARKRED><b><code>ksh -options scriptname</code></b></font> +Startup options. <font color=DARKRED><b><code>ksh -options scriptname</code></b></font>
 <DL> <DL>
 <DT>-x <DT>-x
Line 976: Line 978:
  
 <p align=RIGHT class="newpage"><font size=-1>(13)</font></P> <p align=RIGHT class="newpage"><font size=-1>(13)</font></P>
-<font color=DARKBLUE><h1>Command Substitution</H1></font>+<font color=DARKBLUE>======Command Substitution</H1></font>
  
-<h3>sh syntax</h3>+====sh syntax====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>`command`</code></b></font> <DT><font color=DARKRED><b><code>`command`</code></b></font>
Line 987: Line 989:
  
 </DL> </DL>
-<h3>ksh/bash syntax</h3>+====ksh/bash syntax====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$(command)</code></b></font> <DT><font color=DARKRED><b><code>$(command)</code></b></font>
-<DD>This syntax is functionally the same as backticks, but commands can be more easily nested.  +<DD>This syntax is functionally the same as backticks, but commands can be more easily nested.
 <DT><font color=DARKRED><b><code>$(&lt;file)</code></b></font> <DT><font color=DARKRED><b><code>$(&lt;file)</code></b></font>
 <DD>This is equivalent to <font color=DARKRED><b><code>`cat file`</code></b></font>, but implemented internally for efficiency. <DD>This is equivalent to <font color=DARKRED><b><code>`cat file`</code></b></font>, but implemented internally for efficiency.
Line 1000: Line 1002:
 <code><font color=DARKRED> <code><font color=DARKRED>
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font>
-<font color=GRAY>   2:</font> +<font color=GRAY>   2:</font>
  
 <font color=GRAY>   3:</font> <font color=DARKBLUE>echo </font>Today is `<font color=PURPLE>date</font>` <font color=GRAY>   3:</font> <font color=DARKBLUE>echo </font>Today is `<font color=PURPLE>date</font>`
-<font color=GRAY>   4:</font> +<font color=GRAY>   4:</font>
 <font color=GRAY>   5:</font> <font color=BLACK>file=</font>/etc/hosts <font color=GRAY>   5:</font> <font color=BLACK>file=</font>/etc/hosts
 <font color=GRAY>   6:</font> <font color=DARKBLUE>echo </font>The file <font color=BLACK>$file</font> has $(<font color=PURPLE>wc -l &lt; <font color=BLACK>$file</font></font>) lines <font color=GRAY>   6:</font> <font color=DARKBLUE>echo </font>The file <font color=BLACK>$file</font> has $(<font color=PURPLE>wc -l &lt; <font color=BLACK>$file</font></font>) lines
  
-<font color=GRAY>   7:</font> +<font color=GRAY>   7:</font>
 <font color=GRAY>   8:</font> hostname -s &gt; myhostname <font color=GRAY>   8:</font> hostname -s &gt; myhostname
 <font color=GRAY>   9:</font> <font color=DARKBLUE>echo </font>This system has host name $(<font color=PURPLE>&lt;myhostname</font>) <font color=GRAY>   9:</font> <font color=DARKBLUE>echo </font>This system has host name $(<font color=PURPLE>&lt;myhostname</font>)
Line 1022: Line 1024:
  
 <p align=RIGHT class="newpage"><font size=-1>(14)</font></P> <p align=RIGHT class="newpage"><font size=-1>(14)</font></P>
-<font color=DARKBLUE><h1>I/O redirection and pipelines</H1></font>+<font color=DARKBLUE>======I/O redirection and pipelines</H1></font>
  
 Any simple command (or shell function, or compound command) may have its input and output Any simple command (or shell function, or compound command) may have its input and output
Line 1029: Line 1031:
 the command is run. the command is run.
  
-<h2>Output redirection</h2>+=====Output redirection=====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>&gt; <I>filename</I></code></b></font> <DT><font color=DARKRED><b><code>&gt; <I>filename</I></code></b></font>
Line 1045: Line 1047:
 </DL> </DL>
  
-<h2>Input redirection</h2>+=====Input redirection=====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>&lt; <I>filename</I></code></b></font> <DT><font color=DARKRED><b><code>&lt; <I>filename</I></code></b></font>
Line 1053: Line 1055:
 </DL> </DL>
  
-<h2>Command pipelines</h2>+=====Command pipelines=====
 <DL> <DL>
-<DT><font color=DARKRED><b><code>command | command [[|| command ...]]</code></b></font>+<DT><font color=DARKRED><b><code>command | command [[ | command ...]]</code></b></font>
 <DD>Pipe multiple commands together.  The standard output of the first command becomes the standard <DD>Pipe multiple commands together.  The standard output of the first command becomes the standard
 input of the second command.  All commands run simultaneously, and data transfer happens via memory input of the second command.  All commands run simultaneously, and data transfer happens via memory
Line 1061: Line 1063:
 used with pipes.  Pipes play very nicely with multiprocessor systems. used with pipes.  Pipes play very nicely with multiprocessor systems.
 <blockquote><small> <blockquote><small>
-No more than one command in a pipeline should be interactive (attempt to read from +No more than one command in a pipeline should be interactive (attempt to read from
 the terminal).  This construct is much more efficient than using temporary files, and most standard the terminal).  This construct is much more efficient than using temporary files, and most standard
 Unix utilities are designed such that they work well in pipelines. Unix utilities are designed such that they work well in pipelines.
Line 1079: Line 1081:
  
 <p align=RIGHT class="newpage"><font size=-1>(15)</font></P> <p align=RIGHT class="newpage"><font size=-1>(15)</font></P>
-<font color=DARKBLUE><h1>Input and Output</H1></font>+<font color=DARKBLUE>======Input and Output</H1></font>
  
 Shell scripts can generate output directly or read input into variables using the following commands: Shell scripts can generate output directly or read input into variables using the following commands:
  
-<h3>Script output</h3>+====Script output====
  
 <DL> <DL>
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=echo&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>echo</code></b></font></a> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=echo&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>echo</code></b></font></a>
-<DD>Print arguments, separated by spaces, and terminated by a newline, to stdout.  +<DD>Print arguments, separated by spaces, and terminated by a newline, to stdout.
 Use quotes to preserve spacing.  Echo also understands C-like escape conventions. Use quotes to preserve spacing.  Echo also understands C-like escape conventions.
 <blockquote><small> <blockquote><small>
Line 1094: Line 1096:
 Internal in most shells, but was originally external. Internal in most shells, but was originally external.
 <TABLE width=100%> <TABLE width=100%>
-<TR><TD> \b </TD><TD>  backspace </TD><TD> \c </TD><TD>  print line without new-line (some versions)</TD>+<TR><TD> \\b </TD><TD>  backspace </TD><TD> \\c </TD><TD>  print line without new-line (some versions)</TD>
  
-<TR><TD> \f </TD><TD>  form-feed </TD><TD>\</TD><TD>  new-line </TD> +<TR><TD> \\f </TD><TD>  form-feed </TD><TD>\ 
-<TR><TD> \r </TD><TD>  carriage return</TD><TD> \t </TD><TD>  tab </TD>+<code> 
 + </TD><TD>  new-line </TD
 +</code
 +<TR><TD> \\r </TD><TD>  carriage return</TD><TD> \\t </TD><TD>  tab </TD>
  
-<TR><TD> \v </TD><TD>  vertical tab </TD><TD>\\  </TD><TD> backslash </TD>+<TR><TD> \\v </TD><TD>  vertical tab </TD><TD>\\\\  </TD><TD> backslash </TD>
 </TABLE> </TABLE>
-\0n  where n is the 8-bit character whose ASCII +0n  where n is the 8-bit character whose ASCII 
 +<code>
       code is the 1-, 2- or 3-digit octal number  </TD>       code is the 1-, 2- or 3-digit octal number  </TD>
       representing that character.       representing that character.
 +</code>
 </small></blockquote> </small></blockquote>
 <DL> <DL>
Line 1110: Line 1117:
 </DL> </DL>
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=print&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>print</code></b></font></a> (ksh internal) <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=print&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>print</code></b></font></a> (ksh internal)
-<DD>Print arguments, separated by spaces, and terminated by a newline, to stdout.  +<DD>Print arguments, separated by spaces, and terminated by a newline, to stdout.
 Print observes the same escape conventions as echo. Print observes the same escape conventions as echo.
 <DL> <DL>
Line 1116: Line 1123:
 <DD>suppress newline <DD>suppress newline
 <DT>-r <DT>-r
-<DD>raw mode - ignore \-escape conventions+<DD>raw mode - ignore \\-escape conventions
 <DT>-R <DT>-R
-<DD>raw mode - ignore \-escape conventions and -options except -n.+<DD>raw mode - ignore \\-escape conventions and -options except -n.
 </DL> </DL>
 </DL> </DL>
  
-<h3>Script input</h3>+====Script input====
  
 <DL> <DL>
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=read&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>read</code></b></font></a> <font color=DARKRED><b><code>var1 var2 rest</code></b></font> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=read&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>read</code></b></font></a> <font color=DARKRED><b><code>var1 var2 rest</code></b></font>
 <DD>read a line from stdin, parsing by $IFS, and placing the words into the named variables. <DD>read a line from stdin, parsing by $IFS, and placing the words into the named variables.
-Any left over words all go into the last variable.  A  '\' as the last character on a line+Any left over words all go into the last variable.  A  '\\' as the last character on a line
 removes significance of the newline, and input continues with the following line. removes significance of the newline, and input continues with the following line.
 <DL> <DL>
 <DT>-r <DT>-r
-<DD>raw mode - ignore \-escape conventions+<DD>raw mode - ignore \\-escape conventions
 </DL> </DL>
 </DL> </DL>
Line 1143: Line 1150:
 <font color=GRAY>   3:</font> <font color=DARKBLUE>read </font>x more <font color=GRAY>   3:</font> <font color=DARKBLUE>read </font>x more
  
-<font color=GRAY>   4:</font> <font color=DARKBLUE>echo </font>"First word was \"<font color=BLACK>$x</font>\"" +<font color=GRAY>   4:</font> <font color=DARKBLUE>echo </font>"First word was \\"<font color=BLACK>$x</font>\\"" 
-<font color=GRAY>   5:</font> <font color=DARKBLUE>echo </font>"Rest of the line (if any) was \"<font color=BLACK>$more</font>\""+<font color=GRAY>   5:</font> <font color=DARKBLUE>echo </font>"Rest of the line (if any) was \\"<font color=BLACK>$more</font>\\""
 </font></code> </font></code>
  
Line 1157: Line 1164:
  
 <p align=RIGHT class="newpage"><font size=-1>(16)</font></P> <p align=RIGHT class="newpage"><font size=-1>(16)</font></P>
-<font color=DARKBLUE><h1>Conditional tests for [[...]] and [[...]] commands</H1></font>+<font color=DARKBLUE>======Conditional tests for [[...]] and [[...]] commands</H1></font>
  
 Most of the useful flow-control operators involve making some conditional test and Most of the useful flow-control operators involve making some conditional test and
 branching on the result (true/false).  The test can be either the <a href="http://www.FreeBSD.org/cgi/man.cgi?query=test&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>test</code></b></font></a> branching on the result (true/false).  The test can be either the <a href="http://www.FreeBSD.org/cgi/man.cgi?query=test&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>test</code></b></font></a>
-command, or its alias, <font color=DARKRED><b><code>[</code></b></font>, or the ksh/bash built-in <font color=DARKRED><b><code>[[ ... ]]</code></b></font>+command, or its alias, <font color=DARKRED><b><code>[[</code></b></font>, or the ksh/bash built-in <font color=DARKRED><b><code>[[ ... ]]</code></b></font>
  
 command, which has slightly different options, or it can be <EM>any command which returns command, which has slightly different options, or it can be <EM>any command which returns
Line 1167: Line 1174:
 Note that this is backwards from the C language convention. Note that this is backwards from the C language convention.
  
-<h3>File tests</h3>+====File tests====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>-e <I>file</I></code></b></font> <DT><font color=DARKRED><b><code>-e <I>file</I></code></b></font>
Line 1178: Line 1185:
 <DT><font color=DARKRED><b><code>-r <I>file</I></code></b></font> <DT><font color=DARKRED><b><code>-r <I>file</I></code></b></font>
 <DD>True if <I>file</I> exists and is readable<BR> <DD>True if <I>file</I> exists and is readable<BR>
 +<code>
   Similarly, <font color=DARKRED><b><code>-w</code></b></font> = writable, <font color=DARKRED><b><code>-x</code></b></font> = executable, <font color=DARKRED><b><code>-L</code></b></font> = is a symlink.   Similarly, <font color=DARKRED><b><code>-w</code></b></font> = writable, <font color=DARKRED><b><code>-x</code></b></font> = executable, <font color=DARKRED><b><code>-L</code></b></font> = is a symlink.
 +</code>
  
 <DT><font color=DARKRED><b><code>-s <I>file</I></code></b></font> <DT><font color=DARKRED><b><code>-s <I>file</I></code></b></font>
Line 1187: Line 1196:
 </DL> </DL>
  
-<h3>Character string tests</h3>+====Character string tests====
  
 <DL> <DL>
Line 1196: Line 1205:
  
 <blockquote><small> <blockquote><small>
-With <font color=DARKRED><b><code>[[</code></b></font>,|the argument must be quoted, because if it is a variable that +With <font color=DARKRED><b><code>[[</code></b></font>, the argument must be quoted, because if it is a variable that 
-has a null value, the resulting expansion ( [ -z ]] ) is a syntax error.  An+has a null value, the resulting expansion ( [[ -z ]] ) is a syntax error.  An
 expansion resulting in "" counts as a null string.  <BR> expansion resulting in "" counts as a null string.  <BR>
  
-For <font color=DARKRED><b><code>[[</code></b></font>|only, a quoted +For <font color=DARKRED><b><code>[[</code></b></font> only, a quoted 
-string alone is equivalent to the -n test, e.g. [ "$var" ]].  In older shells for which  +string alone is equivalent to the -n test, e.g. [[ "$var" ]].  In older shells for which 
-<font color=DARKRED><b><code>[[</code></b></font>|is an external program, the only way to test for a null string is:<BR> +<font color=DARKRED><b><code>[[</code></b></font> is an external program, the only way to test for a null string is:<BR> 
-<font color=DARKRED><b><code>if [ "X$var" = "X" ]]</code></b></font><BR>+<font color=DARKRED><b><code>if [[ "X$var" = "X" ]]</code></b></font><BR>
 This is rarely needed now, but is still often found. This is rarely needed now, but is still often found.
 </small></blockquote> </small></blockquote>
Line 1212: Line 1221:
 <DT><font color=DARKRED><b><code>$variable &lt; <I>text</I></code></b></font> <DT><font color=DARKRED><b><code>$variable &lt; <I>text</I></code></b></font>
 <DD>True if <I>$variable</I> comes before (lexically) <I>text</I><BR> <DD>True if <I>$variable</I> comes before (lexically) <I>text</I><BR>
- Similarly, <font color=DARKRED><b><code>&gt;</code></b></font> = comes after +<code> 
 + Similarly, <font color=DARKRED><b><code>&gt;</code></b></font> = comes after 
 +</code>
 </DL> </DL>
  
Line 1222: Line 1233:
  
 <p align=RIGHT class="newpage"><font size=-1>(17)</font></P> <p align=RIGHT class="newpage"><font size=-1>(17)</font></P>
-<font color=DARKBLUE><h1>More conditional tests for [[...]] and [[...]] commands</H1></font>+<font color=DARKBLUE>======More conditional tests for [[...]] and [[...]] commands</H1></font>
  
-<h3>Arithmetic tests</h3>+====Arithmetic tests====
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$variable -eq  <I>number</I></code></b></font> <DT><font color=DARKRED><b><code>$variable -eq  <I>number</I></code></b></font>
Line 1232: Line 1243:
 <DD>True if <I>$variable</I>, interpreted as a number, is <B>not</B> equal to <I>number</I>.<BR> <DD>True if <I>$variable</I>, interpreted as a number, is <B>not</B> equal to <I>number</I>.<BR>
  
- Similarly, <font color=DARKRED><b><code>-lt</code></b></font> = less than, <font color=DARKRED><b><code>-le</code></b></font> = less than or equal,  +<code> 
 + Similarly, <font color=DARKRED><b><code>-lt</code></b></font> = less than, <font color=DARKRED><b><code>-le</code></b></font> = less than or equal, 
 +</code>
 <font color=DARKRED><b><code>-gt</code></b></font> = greater than, <font color=DARKRED><b><code>-ge</code></b></font> = greater than or equal <font color=DARKRED><b><code>-gt</code></b></font> = greater than, <font color=DARKRED><b><code>-ge</code></b></font> = greater than or equal
 </DL> </DL>
  
-<h3>Additional tests for [[...]] (ksh and bash)</h3>+====Additional tests for [[...]] (ksh and bash)====
  
 <DL> <DL>
 <DT><font color=DARKRED><b><code>$variable = <I>pattern</I></code></b></font> <DT><font color=DARKRED><b><code>$variable = <I>pattern</I></code></b></font>
 <DD>True if <I>$variable</I> matches <I>pattern</I> If <I>pattern</I> contains no wildcards, <DD>True if <I>$variable</I> matches <I>pattern</I> If <I>pattern</I> contains no wildcards,
-then this is just an exact text match.  The same wildcards as used for filename matching are used.  +then this is just an exact text match.  The same wildcards as used for filename matching are used.
 <blockquote><small> <blockquote><small>
 The <I>pattern</I> must not be quoted.  Since [[...]] is internal to the shell, the pattern in this case is The <I>pattern</I> must not be quoted.  Since [[...]] is internal to the shell, the pattern in this case is
Line 1257: Line 1270:
  
  
-<h3>Negating and Combining tests</h3>+====Negating and Combining tests====
  
-Tests may be negated by prepending the <font color=DARKRED><b><code>!</code></b></font> operator, and combined with boolean +Tests may be negated by prepending the <font color=DARKRED><b><code>!</code></b></font> operator, and combined with boolean
 <B>AND</B> and <B>OR</B> operators using the syntax: <B>AND</B> and <B>OR</B> operators using the syntax:
 <DL> <DL>
  
 <DT><font color=DARKRED><b><code><I>conditional</I> -a <I>conditional</I>, <I>conditional</I> -o <I>conditional</I> </code></b></font> <DT><font color=DARKRED><b><code><I>conditional</I> -a <I>conditional</I>, <I>conditional</I> -o <I>conditional</I> </code></b></font>
-<DD><B>AND</B> and <B>OR</B> syntax for <font color=DARKRED><b><code>test</code></b></font> and <font color=DARKRED><b><code>[</code></b></font>+<DD><B>AND</B> and <B>OR</B> syntax for <font color=DARKRED><b><code>test</code></b></font> and <font color=DARKRED><b><code>[[</code></b></font>
  
 <P> <P>
Line 1275: Line 1288:
 <I>Examples:</I> <I>Examples:</I>
 <PRE> <PRE>
-if [[  -x /usr/local/bin/lserve && \+if [[  -x /usr/local/bin/lserve && \
 +<code>
        -w /var/logs/lserve.log ]]; then        -w /var/logs/lserve.log ]]; then
    /usr/local/bin/lserve >> /var/logs/lserve.log &    /usr/local/bin/lserve >> /var/logs/lserve.log &
 +</code>
 fi fi
  
 pwent=`grep '^richard:' /etc/passwd` pwent=`grep '^richard:' /etc/passwd`
-if [[|-z "$pwent" ]]; then+if [[ -z "$pwent" ]]; then 
 +<code>
    echo richard not found    echo richard not found
 +</code>
 fi fi
 </PRE> </PRE>
Line 1293: Line 1310:
  
 <p align=RIGHT class="newpage"><font size=-1>(18)</font></P> <p align=RIGHT class="newpage"><font size=-1>(18)</font></P>
-<font color=DARKBLUE><h1>Flow Control and Compound Commands</H1></font>+<font color=DARKBLUE>======Flow Control and Compound Commands</H1></font>
  
 A <I>list</I> in these descriptions is a simple command, or a pipeline. A <I>list</I> in these descriptions is a simple command, or a pipeline.
-The value of the <I>list</I> is the value of the last simple command run in it. +The value of the <I>list</I> is the value of the last simple command run in it.
 <blockquote><small> <blockquote><small>
 A <I>list</I> can also be a set of simple commands or A <I>list</I> can also be a set of simple commands or
 pipelines separated by ";,&,&&,||,|&". pipelines separated by ";,&,&&,||,|&".
 For the compound commands which branch on the success or failure For the compound commands which branch on the success or failure
-of some <I>list</I>,  it is usually <font color=DARKRED><b><code>[[</code></b></font>|or <font color=DARKRED><b><code>[[</code></b></font>, but can be anything.+of some <I>list</I>,  it is usually <font color=DARKRED><b><code>[[</code></b></font> or <font color=DARKRED><b><code>[[</code></b></font>, but can be anything.
  
 </small></blockquote> </small></blockquote>
  
-<h3>Conditional execution: if/else</h3>+====Conditional execution: if/else====
  
 <DL> <DL>
Line 1325: Line 1342:
  
 <PRE> <PRE>
-mkdir tempdir &amp;&amp; cp workfile tempdir || \+mkdir tempdir &amp;&amp; cp workfile tempdir || \
 +<code>
  echo "Failed to create tempdir"  echo "Failed to create tempdir"
 +</code>
 </PRE> </PRE>
 </small></blockquote> </small></blockquote>
Line 1337: Line 1356:
 <I>Example:</I> <I>Example:</I>
 <PRE> <PRE>
-if [ -r $myfile ]]+if [[ -r $myfile ]]
 then then
 +<code>
    cat $myfile    cat $myfile
 +</code>
 else else
 +<code>
    echo $myfile not readable    echo $myfile not readable
 +</code>
 fi fi
 </PRE> </PRE>
 </DL> </DL>
  
-<h3>Looping: 'while' and 'for' loops</h3>+====Looping: 'while' and 'for' loops====
  
 <DL> <DL>
Line 1375: Line 1398:
 </SMALL></BLOCKQUOTE> </SMALL></BLOCKQUOTE>
  
-<DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=for&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>for</code></b></font></a> <font color=DARKRED><b><code><I>identifier</I> [[|in <I>words</I> ]]; do; <I>list</I>; done</code></b></font>+<DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=for&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>for</code></b></font></a> <font color=DARKRED><b><code><I>identifier</I> [[ in <I>words</I> ]]; do; <I>list</I>; done</code></b></font>
  
 <DD>Set <I>identifier</I> in turn to each word in  <I>words</I> and execute the <I>list</I>. <DD>Set <I>identifier</I> in turn to each word in  <I>words</I> and execute the <I>list</I>.
-Omitting the "in <I>words</I>" clause implies using $@, i.e. the <I>identifier</I> is set in +Omitting the "in <I>words</I>" clause implies using $@, i.e. the <I>identifier</I> is set in
 turn to each positional argument. turn to each positional argument.
 <P> <P>
Line 1386: Line 1409:
 for file in *.dat for file in *.dat
 do do
 +<code>
     echo Processing $file     echo Processing $file
 +</code>
 done done
 </PRE> </PRE>
  
 </DL> </DL>
-As with most programming languages, there are often several ways to express the same action.  +As with most programming languages, there are often several ways to express the same action.
 Running a command and then explicitly examining <font color=DARKRED><b><code>$?</code></b></font> can be used instead of some of the above. Running a command and then explicitly examining <font color=DARKRED><b><code>$?</code></b></font> can be used instead of some of the above.
 <P> <P>
Line 1397: Line 1422:
 can have I/O redirection independant of the rest of the script.  Setting of variables in a real subshell does not can have I/O redirection independant of the rest of the script.  Setting of variables in a real subshell does not
 leave them set in the parent script.  Setting variables in implicit subshells varies in behaviour among shells. leave them set in the parent script.  Setting variables in implicit subshells varies in behaviour among shells.
-Older <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sh</code></b></font></a> could not set variables in an implicit subshell and then use them later,  +Older <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sh</code></b></font></a> could not set variables in an implicit subshell and then use them later, 
-but current <a href="http://www.FreeBSD.org/cgi/man.cgi?query=ksh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>ksh</code></b></font></a> can do this (mostly). +but current <a href="http://www.FreeBSD.org/cgi/man.cgi?query=ksh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>ksh</code></b></font></a> can do this (mostly).
  
 <P> <P>
 <I>Example:</I> ex11 <A HREF=ex11.html TARGET=example>display</A>, <A HREF=ex11.txt TARGET=example>text</A><BR> <I>Example:</I> ex11 <A HREF=ex11.html TARGET=example>display</A>, <A HREF=ex11.txt TARGET=example>text</A><BR>
-Reading a file line by line.  The book by Randal Michael contains 12 example ways to read a file line by line, +Reading a file line by line.  The book by Randal Michael contains 12 example ways to read a file line by line,
 which vary tremendously in efficiency.  This example shows the simplest and fastest way. which vary tremendously in efficiency.  This example shows the simplest and fastest way.
 <BLOCKQUOTE><SMALL> <BLOCKQUOTE><SMALL>
 <code><font color=DARKRED> <code><font color=DARKRED>
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/sh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/sh</i></font>
-<font color=GRAY>   2:</font> +<font color=GRAY>   2:</font>
  
 <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Demonstrate reading a file line-by-line, using I/O</i></font> <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Demonstrate reading a file line-by-line, using I/O</i></font>
Line 1414: Line 1439:
 <font color=GRAY>   6:</font> <font color=DARKGREEN><i># Test this under sh and ksh and compare the output.</i></font> <font color=GRAY>   6:</font> <font color=DARKGREEN><i># Test this under sh and ksh and compare the output.</i></font>
  
-<font color=GRAY>   7:</font> +<font color=GRAY>   7:</font>
 <font color=GRAY>   8:</font> <font color=BLACK>line=</font>"TEST" <font color=GRAY>   8:</font> <font color=BLACK>line=</font>"TEST"
 <font color=GRAY>   9:</font> <font color=BLACK>save=</font> <font color=GRAY>   9:</font> <font color=BLACK>save=</font>
-<font color=GRAY>  10:</font>  +<font color=GRAY>  10:</font> 
-<font color=GRAY>  11:</font> <font color=DARKBLUE>if </font>[ -z "<font color=BLACK>$1</font>" ]; <font color=DARKBLUE>then</font>+<font color=GRAY>  11:</font> <font color=DARKBLUE>if </font>[[ -z "<font color=BLACK>$1</font>" ]]; <font color=DARKBLUE>then</font>
  
 <font color=GRAY>  12:</font>    <font color=DARKBLUE>echo </font>"Usage: <font color=BLACK>$0</font> filename" <font color=GRAY>  12:</font>    <font color=DARKBLUE>echo </font>"Usage: <font color=BLACK>$0</font> filename"
 <font color=GRAY>  13:</font> <font color=DARKBLUE>else</font> <font color=GRAY>  13:</font> <font color=DARKBLUE>else</font>
-<font color=GRAY>  14:</font>    <font color=DARKBLUE>if </font>[ -r <font color=BLACK>$1</font> ]; <font color=DARKBLUE>then</font>+<font color=GRAY>  14:</font>    <font color=DARKBLUE>if </font>[[ -r <font color=BLACK>$1</font> ]]; <font color=DARKBLUE>then</font>
  
 <font color=GRAY>  15:</font>       <font color=DARKBLUE>while </font>read line; <font color=DARKBLUE>do</font> <font color=GRAY>  15:</font>       <font color=DARKBLUE>while </font>read line; <font color=DARKBLUE>do</font>
Line 1432: Line 1457:
 <font color=GRAY>  20:</font> <font color=DARKBLUE>fi</font> <font color=GRAY>  20:</font> <font color=DARKBLUE>fi</font>
  
-<font color=GRAY>  21:</font> <font color=DARKBLUE>echo </font>"End value of \<font color=BLACK>$line</font> is <font color=BLACK>$line</font>" +<font color=GRAY>  21:</font> <font color=DARKBLUE>echo </font>"End value of \\<font color=BLACK>$line</font> is <font color=BLACK>$line</font>" 
-<font color=GRAY>  22:</font> <font color=DARKBLUE>echo </font>"End value of \<font color=BLACK>$save</font> is <font color=BLACK>$save</font>"+<font color=GRAY>  22:</font> <font color=DARKBLUE>echo </font>"End value of \\<font color=BLACK>$save</font> is <font color=BLACK>$save</font>"
  
 </font></code> </font></code>
Line 1448: Line 1473:
  
 <p align=RIGHT class="newpage"><font size=-1>(19)</font></P> <p align=RIGHT class="newpage"><font size=-1>(19)</font></P>
-<font color=DARKBLUE><h1>Flow Control and Compound Commands (contd.)</H1></font>+<font color=DARKBLUE>======Flow Control and Compound Commands (contd.)</H1></font>
  
-<h3>Case statement: pattern matching</h3>+====Case statement: pattern matching====
 <DL> <DL>
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=case&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>case</code></b></font></a> <font color=DARKRED><b><code><I>word</I> in <I>pattern</I>) <I>list</I>;; esac</code></b></font> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=case&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>case</code></b></font></a> <font color=DARKRED><b><code><I>word</I> in <I>pattern</I>) <I>list</I>;; esac</code></b></font>
Line 1482: Line 1507:
 <I>Example:</I> <I>Example:</I>
 <PRE> <PRE>
 +<code>
     case $filename in     case $filename in
     *.dat)     *.dat)
Line 1494: Line 1520:
         ;;         ;;
     esac     esac
 +</code>
 </PRE> </PRE>
 </DL> </DL>
  
-<h3>Miscellaneous flow control and subshells</h3>+====Miscellaneous flow control and subshells====
  
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=break&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>break</code></b></font></a> <font color=DARKRED><b><code>[[n]]</code></b></font> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=break&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>break</code></b></font></a> <font color=DARKRED><b><code>[[n]]</code></b></font>
Line 1506: Line 1533:
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=continue&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>continue</code></b></font></a> <font color=DARKRED><b><code>[[n]];</code></b></font> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=continue&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>continue</code></b></font></a> <font color=DARKRED><b><code>[[n]];</code></b></font>
 <DD>Resume iteration of the current (or n'th) enclosing loop.  Control jumps to the top of the loop, <DD>Resume iteration of the current (or n'th) enclosing loop.  Control jumps to the top of the loop,
-which generally causes re-evaluation of a <a href="http://www.FreeBSD.org/cgi/man.cgi?query=while&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>while</code></b></font></a> or processing the next element of a +which generally causes re-evaluation of a <a href="http://www.FreeBSD.org/cgi/man.cgi?query=while&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>while</code></b></font></a> or processing the next element of a
 <a href="http://www.FreeBSD.org/cgi/man.cgi?query=for&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>for</code></b></font></a>. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=for&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>for</code></b></font></a>.
 <P> <P>
Line 1517: Line 1544:
  
 <DT><font color=DARKRED><b><code>( ... )</code></b></font> Command grouping <DT><font color=DARKRED><b><code>( ... )</code></b></font> Command grouping
-<DD>Commands grouped in "( )" are executed in a subshell, with a separate environment  +<DD>Commands grouped in "( )" are executed in a subshell, with a separate environment 
-(can not affect the variables in the rest of the script).  +(can not affect the variables in the rest of the script).
 </DL> </DL>
  
Line 1529: Line 1556:
  
 <p align=RIGHT class="newpage"><font size=-1>(20)</font></P> <p align=RIGHT class="newpage"><font size=-1>(20)</font></P>
-<font color=DARKBLUE><h1>Conditional Test Examples</H1></font>+<font color=DARKBLUE>======Conditional Test Examples</H1></font>
  
 As with most aspects of shell scripting, there are usually several possible ways to accomplish As with most aspects of shell scripting, there are usually several possible ways to accomplish
-a task.  Certain idioms show up commonly.  These are five ways to examine and branch on the +a task.  Certain idioms show up commonly.  These are five ways to examine and branch on the
 initial character of a string. initial character of a string.
 <DL> <DL>
 <DT>Use <font color=DARKRED><b><code>case</code></b></font> with a pattern: <DT>Use <font color=DARKRED><b><code>case</code></b></font> with a pattern:
 <DD><font color=DARKRED><b><code>case $var in</code></b></font><BR> <DD><font color=DARKRED><b><code>case $var in</code></b></font><BR>
 +<code>
     <font color=DARKRED><b><code>/*) echo "starts with /" ;; </code></b></font>     <font color=DARKRED><b><code>/*) echo "starts with /" ;; </code></b></font>
 +</code>
 <BR> <BR>
 Works in all shells, and uses no extra processes Works in all shells, and uses no extra processes
Line 1544: Line 1573:
 <DT>Use <font color=DARKRED><b><code>`cut`</code></b></font>> <DT>Use <font color=DARKRED><b><code>`cut`</code></b></font>>
  
-<DD><font color=DARKRED><b><code>if [[|"`echo $var | cut -c1`" = "/" ]] ; then </code></b></font>.+<DD><font color=DARKRED><b><code>if [[ "`echo $var | cut -c1`" = "/" ]] ; then </code></b></font>.
 <BR>Works in all shells, but inefficiently uses a pipe and external process for a trivial task. <BR>Works in all shells, but inefficiently uses a pipe and external process for a trivial task.
  
 <P> <P>
 <DT>Use POSIX variable truncation: <DT>Use POSIX variable truncation:
-<DD><font color=DARKRED><b><code>if [[|"${var%${var#?}}" = "/" ]]; then</code></b></font>+<DD><font color=DARKRED><b><code>if [[ "${var%${var#?}}" = "/" ]]; then</code></b></font>
 <BR> <BR>
 Works with ksh, bash and other POSIX-compliant shells.  Not obvious if you have not seen Works with ksh, bash and other POSIX-compliant shells.  Not obvious if you have not seen
Line 1571: Line 1600:
 <P> <P>
 <DT>Use ksh (93 and later) and bash variable substrings: <DT>Use ksh (93 and later) and bash variable substrings:
-<DD><font color=DARKRED><b><code>if [[|"${var:0:1}" = "/" ]]; then</code></b></font>+<DD><font color=DARKRED><b><code>if [[ "${var:0:1}" = "/" ]]; then</code></b></font>
 <BR> <BR>
 ksh93 and later versions, and bash, have a syntax for directly extracting substrings by character ksh93 and later versions, and bash, have a syntax for directly extracting substrings by character
Line 1588: Line 1617:
  
 <p align=RIGHT class="newpage"><font size=-1>(21)</font></P> <p align=RIGHT class="newpage"><font size=-1>(21)</font></P>
-<font color=DARKBLUE><h1>Miscellaneous internal commands</H1></font>+<font color=DARKBLUE>======Miscellaneous internal commands</H1></font>
  
 The shells (ksh in particular) have many more internal commands.  Some are used more in interactive The shells (ksh in particular) have many more internal commands.  Some are used more in interactive
Line 1598: Line 1627:
 <DD>The args are read as input to the shell and the resulting command executed.  Allows "double" expansion <DD>The args are read as input to the shell and the resulting command executed.  Allows "double" expansion
 of some constructs.  For example, constructing a variable name out of pieces, and then obtaining the value of some constructs.  For example, constructing a variable name out of pieces, and then obtaining the value
-of that variable.  +of that variable.
 <P> <P>
 <PRE> <PRE>
-netdev=NETDEV_ +netdev=NETDEV_
 NETDEV_1=hme0         # As part of an initialization step defining multiple devices NETDEV_1=hme0         # As part of an initialization step defining multiple devices
  
 devnum=1              # As part of a loop over those devices devnum=1              # As part of a loop over those devices
 ifname=$netdev$devnum # construct a variable name NETDEV_1 ifname=$netdev$devnum # construct a variable name NETDEV_1
-eval device=\$$ifname # evaluate it - device is set to hme0+eval device=\\$$ifname # evaluate it - device is set to hme0
 </PRE> </PRE>
  
Line 1619: Line 1648:
 <PRE> <PRE>
 while :; do while :; do
-  # this loop will go forever until broken by +<code> 
 +  # this loop will go forever until broken by
   # a conditional test inside, or a signal   # a conditional test inside, or a signal
 +</code>
 done done
 </PRE> </PRE>
Line 1627: Line 1658:
 <DD>Remove the named variables.  This is not the same as setting their values to null. <DD>Remove the named variables.  This is not the same as setting their values to null.
 <P> <P>
-<DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=typeset&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>typeset</code></b></font></a> <font color=DARKRED><b><code>[[+/-|options]] [ <I>name</I>[[=<I>value</I>]] ] ...</code></b></font> (ksh only, +<DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=typeset&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>typeset</code></b></font></a> <font color=DARKRED><b><code>[[+/- options]] [[ <I>name</I>[[=<I>value</I>]] ] ...</code></b></font> (ksh only,
 bash uses <font color=DARKRED><b><code>declare</code></b></font> for similar functions) bash uses <font color=DARKRED><b><code>declare</code></b></font> for similar functions)
  
Line 1639: Line 1670:
 <DT><font color=DARKRED><b><code>-l</code></b></font> <DT><font color=DARKRED><b><code>-l</code></b></font>
 <DD>The named variable is always treated as an integer.  This makes arithmetic faster.  The reserved word <DD>The named variable is always treated as an integer.  This makes arithmetic faster.  The reserved word
 +<code>
  <font color=DARKRED><b><code>integer</code></b></font> is an alias for <font color=DARKRED><b><code>typeset -i</code></b></font>.  <font color=DARKRED><b><code>integer</code></b></font> is an alias for <font color=DARKRED><b><code>typeset -i</code></b></font>.
 +</code>
 </DL> </DL>
  
Line 1669: Line 1702:
  
 <p align=RIGHT class="newpage"><font size=-1>(22)</font></P> <p align=RIGHT class="newpage"><font size=-1>(22)</font></P>
-<font color=DARKBLUE><h1>Manipulating Variables (ksh/bash only)</H1></font>+<font color=DARKBLUE>======Manipulating Variables (ksh/bash only)</H1></font>
  
-<h2>Text variables</h2>+=====Text variables=====
 The <I>pattern</I> in the following uses the same wildcards as for filename matching. The <I>pattern</I> in the following uses the same wildcards as for filename matching.
 <DL> <DL>
Line 1687: Line 1720:
 </DL> </DL>
  
-<h2>Numeric variables</h2>+=====Numeric variables=====
  
 <DL> <DL>
Line 1694: Line 1727:
 expression (integer only).  Variables are referenced by name without the "$" Most of the arithmetic expression (integer only).  Variables are referenced by name without the "$" Most of the arithmetic
 syntax of the 'C' language is supported, including bit manipulations syntax of the 'C' language is supported, including bit manipulations
 +<code>
  (*,/,+,-,|,&amp;,&lt;&lt;,&gt;&gt;. Use parentheses for changing precedence).  (*,/,+,-,|,&amp;,&lt;&lt;,&gt;&gt;. Use parentheses for changing precedence).
 +</code>
 </DL> </DL>
  
Line 1704: Line 1739:
 <DT><font color=DARKRED><b><code>filename=${datapath##*/}</code></b></font> <DT><font color=DARKRED><b><code>filename=${datapath##*/}</code></b></font>
 <DD><font color=DARKRED><b><code>filename</code></b></font> is set to "datafile.dat" since the longest <I>prefix</I> <DD><font color=DARKRED><b><code>filename</code></b></font> is set to "datafile.dat" since the longest <I>prefix</I>
-pattern matching "*/" is the +pattern matching "*/" is the
 leading directory path (compare <a href="http://www.FreeBSD.org/cgi/man.cgi?query=basename&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>basename</code></b></font></a>) leading directory path (compare <a href="http://www.FreeBSD.org/cgi/man.cgi?query=basename&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>basename</code></b></font></a>)
 <DT><font color=DARKRED><b><code>path=${datapath%/*}</code></b></font> <DT><font color=DARKRED><b><code>path=${datapath%/*}</code></b></font>
 <DD><font color=DARKRED><b><code>path</code></b></font> is set to "/data/public/project/trials/set1" since the shortest <I>suffix</I> <DD><font color=DARKRED><b><code>path</code></b></font> is set to "/data/public/project/trials/set1" since the shortest <I>suffix</I>
  
-pattern matching "/*" is the +pattern matching "/*" is the
 filename in the last directory (compare <a href="http://www.FreeBSD.org/cgi/man.cgi?query=dirname&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>dirname</code></b></font></a>) filename in the last directory (compare <a href="http://www.FreeBSD.org/cgi/man.cgi?query=dirname&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>dirname</code></b></font></a>)
 <P> <P>
 <DT><font color=DARKRED><b><code>i=$((i+1))</code></b></font> <DT><font color=DARKRED><b><code>i=$((i+1))</code></b></font>
-<DD>often used in <font color=DARKRED><b><code>while</code></b></font> loops +<DD>often used in <font color=DARKRED><b><code>while</code></b></font> loops
 </DL> </DL>
  
Line 1723: Line 1758:
  
 <p align=RIGHT class="newpage"><font size=-1>(23)</font></P> <p align=RIGHT class="newpage"><font size=-1>(23)</font></P>
-<font color=DARKBLUE><h1>Shell Functions</H1></font>+<font color=DARKBLUE>======Shell Functions</H1></font>
  
-All but the earliest versions of <font color=DARKRED><b><code>sh</code></b></font> allow you define <I>shell functions</I>, which are visible only +All but the earliest versions of <font color=DARKRED><b><code>sh</code></b></font> allow you define <I>shell functions</I>, which are visible only
 to the shell script and can be used like any other command.  Shell functions take precedence over to the shell script and can be used like any other command.  Shell functions take precedence over
 external commands if the same name is used.  Functions execute in the same process as the caller, external commands if the same name is used.  Functions execute in the same process as the caller,
Line 1731: Line 1766:
 into maintainable chunks, and encourage code reuse between scripts. into maintainable chunks, and encourage code reuse between scripts.
  
-<h3>Defining functions</h3>+====Defining functions====
 <DL> <DL>
 <DT><font color=DARKRED><b><code><I>identifier</I>() { <I>list</I>; }</code></b></font> <DT><font color=DARKRED><b><code><I>identifier</I>() { <I>list</I>; }</code></b></font>
Line 1740: Line 1775:
 but uses a separate namespace. but uses a separate namespace.
 <DT><font color=DARKRED><b><code>function <I>identifier</I> { <I>list</I>; }</code></b></font> <DT><font color=DARKRED><b><code>function <I>identifier</I> { <I>list</I>; }</code></b></font>
-<DD>Ksh and bash optional syntax for defining a function.  These functions may define local +<DD>Ksh and bash optional syntax for defining a function.  These functions may define local
 variables and local signal variables and local signal
 traps and so can more easily avoid side effects and be reused by multiple scripts. traps and so can more easily avoid side effects and be reused by multiple scripts.
Line 1764: Line 1799:
 die() die()
 { {
 +<code>
    # Print an error message and exit with given status    # Print an error message and exit with given status
-   # call as: die status "message" [["message"|...]]+   # call as: die status "message" [["message" ...]]
    exitstat=$1; shift    exitstat=$1; shift
    for i in "$@"; do    for i in "$@"; do
Line 1771: Line 1807:
    done    done
    exit $exitstat    exit $exitstat
 +</code>
 } }
  
 </PRE> </PRE>
  
-<h3>Calling functions.</h3>+====Calling functions.====
  
-Functions are called like any other command.  The output may be redirected independantly of the +Functions are called like any other command.  The output may be redirected independantly of the
 script, and arguments passed to the function.  Shell option flags like -x are unset in a function - you script, and arguments passed to the function.  Shell option flags like -x are unset in a function - you
 must explicitly set them in each function to trace the execution.  Shell functions may even be backgrounded must explicitly set them in each function to trace the execution.  Shell functions may even be backgrounded
Line 1784: Line 1821:
 <I>Example:</I> <I>Example:</I>
 <PRE> <PRE>
-[[|-w $filename ]] || \+[[ -w $filename ]] || \
 +<code>
   die 1 "$file not writeable" "check permissions"   die 1 "$file not writeable" "check permissions"
 +</code>
 </PRE> </PRE>
 <P> <P>
Line 1793: Line 1832:
 <code><font color=DARKRED> <code><font color=DARKRED>
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/sh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/sh</i></font>
-<font color=GRAY>   2:</font> +<font color=GRAY>   2:</font>
 <font color=GRAY>   3:</font> background() <font color=GRAY>   3:</font> background()
 <font color=GRAY>   4:</font> { <font color=GRAY>   4:</font> {
Line 1803: Line 1842:
  
 <font color=GRAY>   9:</font> } <font color=GRAY>   9:</font> }
-<font color=GRAY>  10:</font> +<font color=GRAY>  10:</font>
 <font color=GRAY>  11:</font> <font color=DARKBLUE>echo </font>"ps before background function" <font color=GRAY>  11:</font> <font color=DARKBLUE>echo </font>"ps before background function"
 <font color=GRAY>  12:</font> ps <font color=GRAY>  12:</font> ps
Line 1823: Line 1862:
 vprint() vprint()
 { {
 +<code>
    # Print or not depending on global "$verbosity"    # Print or not depending on global "$verbosity"
    # Change the verbosity with a single variable.    # Change the verbosity with a single variable.
Line 1830: Line 1870:
       print -R $*       print -R $*
    fi    fi
 +</code>
 } }
  
Line 1837: Line 1878:
 </PRE> </PRE>
  
-<h3>Reuseable functions</h3>+====Reuseable functions====
  
 By using only command line arguments, not global variables, and taking care to minimise the side By using only command line arguments, not global variables, and taking care to minimise the side
Line 1856: Line 1897:
  
 <p align=RIGHT class="newpage"><font size=-1>(24)</font></P> <p align=RIGHT class="newpage"><font size=-1>(24)</font></P>
-<font color=DARKBLUE><h1>Advanced I/O</H1></font>+<font color=DARKBLUE>======Advanced I/O</H1></font>
  
-Unix I/O is performed by assigning file descriptors to files or devices, and then +Unix I/O is performed by assigning file descriptors to files or devices, and then
 using those descriptors for reading and writing.  Descriptors 0, 1, and 2 are always using those descriptors for reading and writing.  Descriptors 0, 1, and 2 are always
 used for stdin, stdout and stderr respectively.  Stdin defaults to the keyboard, used for stdin, stdout and stderr respectively.  Stdin defaults to the keyboard,
 while stdout and stderr both default to the current terminal window. while stdout and stderr both default to the current terminal window.
  
-<h3>Redirecting for the whole script</h3>+====Redirecting for the whole script====
  
 Redirecting stdout, stderr and other file descriptors for the whole script Redirecting stdout, stderr and other file descriptors for the whole script
 can be done with the <a href="http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>exec</code></b></font></a> command. can be done with the <a href="http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>exec</code></b></font></a> command.
 <DL> <DL>
 +<code>
  <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>exec</code></b></font></a> <font color=DARKRED><b><code> &gt; outfile &lt; infile </code></b></font>  <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>exec</code></b></font></a> <font color=DARKRED><b><code> &gt; outfile &lt; infile </code></b></font>
  <DD>with no command, the <font color=DARKRED><b><code>exec</code></b></font> just reassigns the I/O of the current shell.  <DD>with no command, the <font color=DARKRED><b><code>exec</code></b></font> just reassigns the I/O of the current shell.
  <DT><font color=DARKRED><b><code>exec n&gt;outfile</code></b></font>  <DT><font color=DARKRED><b><code>exec n&gt;outfile</code></b></font>
 +</code>
  
 +<code>
  <DD>The form n&lt;, n&gt; opens file descriptor n instead of the default stdin/stdout.  <DD>The form n&lt;, n&gt; opens file descriptor n instead of the default stdin/stdout.
 +</code>
 This can then be used with <font color=DARKRED><b><code>read -u</code></b></font> or <font color=DARKRED><b><code>print -u</code></b></font>. This can then be used with <font color=DARKRED><b><code>read -u</code></b></font> or <font color=DARKRED><b><code>print -u</code></b></font>.
 </DL> </DL>
  
-<h3>Explicitly opening or duplicating file descriptors</h3>+====Explicitly opening or duplicating file descriptors====
  
 One reason to do this is to save the current One reason to do this is to save the current
Line 1882: Line 1927:
 <DL> <DL>
  
 +<code>
  <DT><font color=DARKRED><b><code>&gt;&amp;n</code></b></font>  <DT><font color=DARKRED><b><code>&gt;&amp;n</code></b></font>
  <DD>standard output is moved to whatever file descriptor n is currently pointing to  <DD>standard output is moved to whatever file descriptor n is currently pointing to
Line 1889: Line 1935:
  <DD>file descriptor n is opened for writing on the named <I>file</I>.  <DD>file descriptor n is opened for writing on the named <I>file</I>.
  <DT><font color=DARKRED><b><code>n&gt;&amp;1</code></b></font>  <DT><font color=DARKRED><b><code>n&gt;&amp;1</code></b></font>
 +</code>
  
 +<code>
  <DD>file descriptor n is set to whatever file descriptor 1 is currently pointing to.  <DD>file descriptor n is set to whatever file descriptor 1 is currently pointing to.
 +</code>
 </DL> </DL>
 <I>Example</I> Sending messages to stderr (2) instead of stdout (1) <I>Example</I> Sending messages to stderr (2) instead of stdout (1)
 <PRE> <PRE>
-echo "Error: program failed" &gt;&amp;+echo "Error: program failed" &gt;&amp;2
 </PRE> </PRE>
 Echo always writes to stdout, but stdout can be temporarily reassigned to duplicate stderr (or other file Echo always writes to stdout, but stdout can be temporarily reassigned to duplicate stderr (or other file
Line 1900: Line 1949:
 Conventionally Unix programs send error messages to stderr to keep them separated from stdout. Conventionally Unix programs send error messages to stderr to keep them separated from stdout.
  
-<h3>Input and output to open file descriptors (ksh)</h3>+====Input and output to open file descriptors (ksh)====
  
 Printing to file descriptors (usually more efficient than open/append/close): Printing to file descriptors (usually more efficient than open/append/close):
 <DL> <DL>
 +<code>
  <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=print&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>print</code></b></font></a> <font color=DARKRED><b><code> -u <I>n</I> args</code></b></font>  <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=print&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>print</code></b></font></a> <font color=DARKRED><b><code> -u <I>n</I> args</code></b></font>
 +</code>
  
 +<code>
  <DD>print to file descriptor <I>n</I>.  <DD>print to file descriptor <I>n</I>.
  <DT>-p  <DT>-p
  <DD>write to the pipe to a coprocess (opened by |&amp;)  <DD>write to the pipe to a coprocess (opened by |&amp;)
 +</code>
 </DL> </DL>
  
Line 1914: Line 1967:
 Reading from file descriptors other than stdin: Reading from file descriptors other than stdin:
 <DL> <DL>
 +<code>
  <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=read&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>read</code></b></font></a> <font color=DARKRED><b><code> -u <I>n</I> var1 var2 rest</code></b></font>  <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=read&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>read</code></b></font></a> <font color=DARKRED><b><code> -u <I>n</I> var1 var2 rest</code></b></font>
 +</code>
  
- <DD>read a line from file descriptor n, parsing by $IFS, and placing the words into +<code> 
 + <DD>read a line from file descriptor n, parsing by $IFS, and placing the words into 
 +</code>
 the named variables.  Any left over words all go into the last variable. the named variables.  Any left over words all go into the last variable.
 +<code>
  <DT>-p  <DT>-p
  <DD>read from the pipe to a coprocess (opened by |&amp;)  <DD>read from the pipe to a coprocess (opened by |&amp;)
 +</code>
 </DL> </DL>
 <P> <P>
  
-<h3>Closing file handles</h3>+====Closing file handles====
 <DL> <DL>
 +<code>
  <DT><font color=DARKRED><b><code>&lt;&amp;-</code></b></font>  <DT><font color=DARKRED><b><code>&lt;&amp;-</code></b></font>
  <DD>standard input is explicitly closed  <DD>standard input is explicitly closed
  <DT><font color=DARKRED><b><code>&gt;&amp;-</code></b></font>  <DT><font color=DARKRED><b><code>&gt;&amp;-</code></b></font>
 +</code>
  
 +<code>
  <DD>standard output is explicitly closed  <DD>standard output is explicitly closed
 +</code>
 </DL> </DL>
 For example, to indicate to another program downstream in a pipeline that no more For example, to indicate to another program downstream in a pipeline that no more
 data will be coming.  All file descriptors are closed when a script exits. data will be coming.  All file descriptors are closed when a script exits.
 <P> <P>
-I/O redirection operators are evaluated left-to-right.  This makes a difference in a +I/O redirection operators are evaluated left-to-right.  This makes a difference in a
 statement like: statement like:
 "<font color=DARKRED><b><code>&gt;filename&nbsp;2&gt;&amp;1</code></b></font>" (Many books with example scripts get this wrong) "<font color=DARKRED><b><code>&gt;filename&nbsp;2&gt;&amp;1</code></b></font>" (Many books with example scripts get this wrong)
  
-<h3>"Here" documents</h3>+===="Here" documents====
  
 <DL> <DL>
Line 1952: Line 2015:
  
 <font color=GRAY>   2:</font> <font color=DARKBLUE>echo </font>"Example of unquoted here document, with variable and command substitution" <font color=GRAY>   2:</font> <font color=DARKBLUE>echo </font>"Example of unquoted here document, with variable and command substitution"
-<font color=GRAY>   3:</font> +<font color=GRAY>   3:</font>
 <font color=GRAY>   4:</font> cat &lt;&lt;EOF <font color=GRAY>   4:</font> cat &lt;&lt;EOF
-<font color=GRAY>   5:</font>  This text will be fed to the "cat" program as +<font color=GRAY>   5:</font>  This text will be fed to the "cat" program as
  
 <font color=GRAY>   6:</font>  standard input.  It will also have variable <font color=GRAY>   6:</font>  standard input.  It will also have variable
Line 1967: Line 2030:
 <font color=GRAY>  13:</font> cat &lt;&lt;"EndOfInput" <font color=GRAY>  13:</font> cat &lt;&lt;"EndOfInput"
 <font color=GRAY>  14:</font>  This text will be fed to the "cat" program as standard <font color=GRAY>  14:</font>  This text will be fed to the "cat" program as standard
-<font color=GRAY>  15:</font>  input.  Since the text string marking the end was quoted, it does not get +<font color=GRAY>  15:</font>  input.  Since the text string marking the end was quoted, it does not get
 <font color=GRAY>  16:</font>  variable and command subsitutions. <font color=GRAY>  16:</font>  variable and command subsitutions.
  
Line 1984: Line 2047:
  
 <font color=GRAY>   3:</font> <font color=DARKGREEN><i># duplex printer control for Xerox docuprint.</i></font> <font color=GRAY>   3:</font> <font color=DARKGREEN><i># duplex printer control for Xerox docuprint.</i></font>
-<font color=GRAY>   4:</font> +<font color=GRAY>   4:</font>
 <font color=GRAY>   5:</font> <font color=DARKGREEN><i># To have this script send the files directly to the printer, use </i></font> <font color=GRAY>   5:</font> <font color=DARKGREEN><i># To have this script send the files directly to the printer, use </i></font>
 <font color=GRAY>   6:</font> <font color=DARKGREEN><i># a subshell to collect the output of the two 'cat' commands.</i></font> <font color=GRAY>   6:</font> <font color=DARKGREEN><i># a subshell to collect the output of the two 'cat' commands.</i></font>
  
-<font color=GRAY>   7:</font> +<font color=GRAY>   7:</font>
 <font color=GRAY>   8:</font> <font color=DARKGREEN><i><b>## (</b></i></font> <font color=GRAY>   8:</font> <font color=DARKGREEN><i><b>## (</b></i></font>
 <font color=GRAY>   9:</font> cat &lt;&lt; EOP <font color=GRAY>   9:</font> cat &lt;&lt; EOP
Line 2011: Line 2074:
  
 <p align=RIGHT class="newpage"><font size=-1>(25)</font></P> <p align=RIGHT class="newpage"><font size=-1>(25)</font></P>
-<font color=DARKBLUE><h1>Wizard Level I/O</H1></font>+<font color=DARKBLUE>======Wizard Level I/O</H1></font>
  
 More complicated manipulations of file descriptors can be arranged. More complicated manipulations of file descriptors can be arranged.
Line 2028: Line 2091:
 <P> <P>
  
-<h3>Pass stderr of a command into a pipeline for further processing</h3>+====Pass stderr of a command into a pipeline for further processing====
  
 <I>Example:</I> ex14 <A HREF=ex14.html TARGET=example>display</A>, <A HREF=ex14.txt TARGET=example>text</A> <I>Example:</I> ex14 <A HREF=ex14.html TARGET=example>display</A>, <A HREF=ex14.txt TARGET=example>text</A>
Line 2047: Line 2110:
 <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Take stderr from a command and pass it into a pipe</i></font> <font color=GRAY>   3:</font> <font color=DARKGREEN><i># Take stderr from a command and pass it into a pipe</i></font>
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i># for further processing.</i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i># for further processing.</i></font>
-<font color=GRAY>   5:</font> +<font color=GRAY>   5:</font>
  
 <font color=GRAY>   6:</font> <font color=DARKGREEN><i># Uses ex13.sh to generate some output to stderr</i></font> <font color=GRAY>   6:</font> <font color=DARKGREEN><i># Uses ex13.sh to generate some output to stderr</i></font>
 <font color=GRAY>   7:</font> <font color=DARKGREEN><i># stdout of ex13 is processed normally</i></font> <font color=GRAY>   7:</font> <font color=DARKGREEN><i># stdout of ex13 is processed normally</i></font>
-<font color=GRAY>   8:</font> +<font color=GRAY>   8:</font>
 <font color=GRAY>   9:</font> <font color=DARKGREEN><i># Save a copy of original stdout</i></font> <font color=GRAY>   9:</font> <font color=DARKGREEN><i># Save a copy of original stdout</i></font>
  
 <font color=GRAY>  10:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1 <font color=GRAY>  10:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1
-<font color=GRAY>  11:</font> +<font color=GRAY>  11:</font>
 <font color=GRAY>  12:</font> <font color=DARKGREEN><i># stdout from ex13.sh is directed to the original stdout (3)</i></font> <font color=GRAY>  12:</font> <font color=DARKGREEN><i># stdout from ex13.sh is directed to the original stdout (3)</i></font>
 <font color=GRAY>  13:</font> <font color=DARKGREEN><i># stderr is passed into the pipe for further processing.</i></font> <font color=GRAY>  13:</font> <font color=DARKGREEN><i># stderr is passed into the pipe for further processing.</i></font>
Line 2061: Line 2124:
 <font color=GRAY>  14:</font> <font color=DARKGREEN><i># stdout from the pipe is redirected back to stderr</i></font> <font color=GRAY>  14:</font> <font color=DARKGREEN><i># stdout from the pipe is redirected back to stderr</i></font>
 <font color=GRAY>  15:</font> ./ex13.sh 2&gt;&amp;1 1&gt;&amp;3 3&gt;&amp; | sed 's/stderr/STDERR/' 1&gt;&amp;2 <font color=GRAY>  15:</font> ./ex13.sh 2&gt;&amp;1 1&gt;&amp;3 3&gt;&amp; | sed 's/stderr/STDERR/' 1&gt;&amp;2
-<font color=GRAY>  16:</font> +<font color=GRAY>  16:</font>
 <font color=GRAY>  17:</font> <font color=DARKGREEN><i># 3 is closed before running the command, just in case it cares</i></font> <font color=GRAY>  17:</font> <font color=DARKGREEN><i># 3 is closed before running the command, just in case it cares</i></font>
  
Line 2069: Line 2132:
 </SMALL></BLOCKQUOTE> </SMALL></BLOCKQUOTE>
  
-<h3>Capture the exit status of a command in the middle of a pipeline</h3>+====Capture the exit status of a command in the middle of a pipeline====
  
 <I>Example:</I> ex15 <A HREF=ex15.html TARGET=example>display</A>, <A HREF=ex15.txt TARGET=example>text</A> <I>Example:</I> ex15 <A HREF=ex15.html TARGET=example>display</A>, <A HREF=ex15.txt TARGET=example>text</A>
Line 2077: Line 2140:
 <font color=DARKRED><b><code> ex13stat=`((./ex13.sh; echo $? &gt;&amp;4) | grep 'foo' 1&gt;&amp;3) 4&gt;&amp;1` </code></b></font><BR> <font color=DARKRED><b><code> ex13stat=`((./ex13.sh; echo $? &gt;&amp;4) | grep 'foo' 1&gt;&amp;3) 4&gt;&amp;1` </code></b></font><BR>
 <P> <P>
-This script uses nested subshells captured in backtics.  +This script uses nested subshells captured in backtics.
 Again we first duplicate stdout to another file descriptor (3). Again we first duplicate stdout to another file descriptor (3).
 The inner subshell runs the first command, then writes the exit status The inner subshell runs the first command, then writes the exit status
Line 2095: Line 2158:
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/sh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/sh</i></font>
 <font color=GRAY>   2:</font> <font color=DARKGREEN><i># Example 15</i></font> <font color=GRAY>   2:</font> <font color=DARKGREEN><i># Example 15</i></font>
-<font color=GRAY>   3:</font> +<font color=GRAY>   3:</font>
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i># Uses ex13.sh to generate some output and give us an </i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i># Uses ex13.sh to generate some output and give us an </i></font>
  
 <font color=GRAY>   5:</font> <font color=DARKGREEN><i># exit status to capture.</i></font> <font color=GRAY>   5:</font> <font color=DARKGREEN><i># exit status to capture.</i></font>
-<font color=GRAY>   6:</font> +<font color=GRAY>   6:</font>
 <font color=GRAY>   7:</font> <font color=DARKGREEN><i># Get the exit status of ex13 into $ex13stat.  </i></font> <font color=GRAY>   7:</font> <font color=DARKGREEN><i># Get the exit status of ex13 into $ex13stat.  </i></font>
 <font color=GRAY>   8:</font> <font color=DARKGREEN><i># stdout of ex13 is processed normally</i></font> <font color=GRAY>   8:</font> <font color=DARKGREEN><i># stdout of ex13 is processed normally</i></font>
  
-<font color=GRAY>   9:</font> +<font color=GRAY>   9:</font>
 <font color=GRAY>  10:</font> <font color=DARKGREEN><i># Save a copy of stdout</i></font> <font color=GRAY>  10:</font> <font color=DARKGREEN><i># Save a copy of stdout</i></font>
 <font color=GRAY>  11:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1 <font color=GRAY>  11:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1
Line 2120: Line 2183:
 <font color=GRAY>  21:</font> <font color=BLACK>ex13stat=</font>`<font color=PURPLE>((./ex13.sh; <font color=DARKBLUE>echo </font>$? &gt;&amp;4) | grep 'foo' 1&gt;&amp;3) 4&gt;&amp;1</font>` <font color=GRAY>  21:</font> <font color=BLACK>ex13stat=</font>`<font color=PURPLE>((./ex13.sh; <font color=DARKBLUE>echo </font>$? &gt;&amp;4) | grep 'foo' 1&gt;&amp;3) 4&gt;&amp;1</font>`
  
-<font color=GRAY>  22:</font> +<font color=GRAY>  22:</font>
 <font color=GRAY>  23:</font> <font color=DARKBLUE>echo </font>Last command status=$? <font color=GRAY>  23:</font> <font color=DARKBLUE>echo </font>Last command status=$?
 <font color=GRAY>  24:</font> <font color=DARKBLUE>echo </font>ex13stat=<font color=BLACK>$ex13stat</font> <font color=GRAY>  24:</font> <font color=DARKBLUE>echo </font>ex13stat=<font color=BLACK>$ex13stat</font>
-<font color=GRAY>  25:</font> +<font color=GRAY>  25:</font>
  
 <font color=GRAY>  26:</font> <font color=DARKGREEN><i># If any of the commands really care about inheriting open file </i></font> <font color=GRAY>  26:</font> <font color=DARKGREEN><i># If any of the commands really care about inheriting open file </i></font>
Line 2130: Line 2193:
 <font color=GRAY>  29:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1 <font color=GRAY>  29:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1
  
-<font color=GRAY>  30:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 3&gt;&amp;- 4&gt;&amp;- ; <font color=DARKBLUE>echo </font>$? &gt;&amp;4) | \+<font color=GRAY>  30:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 3&gt;&amp;- 4&gt;&amp;- ; <font color=DARKBLUE>echo </font>$? &gt;&amp;4) | \\
 <font color=GRAY>  31:</font>    grep 'foo'  1&gt;&amp;3 3&gt;&amp;- 4&gt;&amp;- ) 4&gt;&amp;1` <font color=GRAY>  31:</font>    grep 'foo'  1&gt;&amp;3 3&gt;&amp;- 4&gt;&amp;- ) 4&gt;&amp;1`
  
Line 2146: Line 2209:
 <P> <P>
 <font color=DARKRED><b><code>exec 3&gt;&amp;1 </code></b></font><BR> <font color=DARKRED><b><code>exec 3&gt;&amp;1 </code></b></font><BR>
-<font color=DARKRED><b><code>ex13stat=`((./ex13.sh 2&gt;&amp;1 1&gt;&amp;3 3&gt;&amp;- 4&gt;&amp;- ; echo $? &gt;&amp;4) | \ </code></b></font><BR>+<font color=DARKRED><b><code>ex13stat=`((./ex13.sh 2&gt;&amp;1 1&gt;&amp;3 3&gt;&amp;- 4&gt;&amp;- ; echo $? &gt;&amp;4) | \\ </code></b></font><BR>
  
 <font color=DARKRED><b><code>  sed s/err/ERR/ 1&gt;&amp;2 3&gt;&amp;- 4&gt;&amp;- ) 4&gt;&amp;1` </code></b></font> <font color=DARKRED><b><code>  sed s/err/ERR/ 1&gt;&amp;2 3&gt;&amp;- 4&gt;&amp;- ) 4&gt;&amp;1` </code></b></font>
Line 2155: Line 2218:
 <font color=GRAY>   2:</font> <font color=DARKGREEN><i># Example 16</i></font> <font color=GRAY>   2:</font> <font color=DARKGREEN><i># Example 16</i></font>
  
-<font color=GRAY>   3:</font> +<font color=GRAY>   3:</font>
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i># Uses ex13.sh to generate some output and give us an </i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i># Uses ex13.sh to generate some output and give us an </i></font>
 <font color=GRAY>   5:</font> <font color=DARKGREEN><i># exit status to capture.</i></font> <font color=GRAY>   5:</font> <font color=DARKGREEN><i># exit status to capture.</i></font>
-<font color=GRAY>   6:</font> +<font color=GRAY>   6:</font>
 <font color=GRAY>   7:</font> <font color=DARKGREEN><i># Get the exit status of ex13 into ex13stat. </i></font> <font color=GRAY>   7:</font> <font color=DARKGREEN><i># Get the exit status of ex13 into ex13stat. </i></font>
  
 <font color=GRAY>   8:</font> <font color=DARKGREEN><i># stderr of ex13 is processed by the pipe, stdout</i></font> <font color=GRAY>   8:</font> <font color=DARKGREEN><i># stderr of ex13 is processed by the pipe, stdout</i></font>
 <font color=GRAY>   9:</font> <font color=DARKGREEN><i># is left alone.</i></font> <font color=GRAY>   9:</font> <font color=DARKGREEN><i># is left alone.</i></font>
-<font color=GRAY>  10:</font> +<font color=GRAY>  10:</font>
 <font color=GRAY>  11:</font> <font color=DARKGREEN><i># Save a copy of stdout</i></font> <font color=GRAY>  11:</font> <font color=DARKGREEN><i># Save a copy of stdout</i></font>
  
 <font color=GRAY>  12:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1 <font color=GRAY>  12:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1
-<font color=GRAY>  13:</font> +<font color=GRAY>  13:</font>
 <font color=GRAY>  14:</font> <font color=DARKGREEN><i># Run a subshell, with 4 copied to 1 so we get it in stdout.  </i></font> <font color=GRAY>  14:</font> <font color=DARKGREEN><i># Run a subshell, with 4 copied to 1 so we get it in stdout.  </i></font>
 <font color=GRAY>  15:</font> <font color=DARKGREEN><i># Capture the output in backtics`</i></font> <font color=GRAY>  15:</font> <font color=DARKGREEN><i># Capture the output in backtics`</i></font>
  
 <font color=GRAY>  16:</font> <font color=DARKGREEN><i># ex13stat=`(    ) 4&gt;&amp;1`</i></font> <font color=GRAY>  16:</font> <font color=DARKGREEN><i># ex13stat=`(    ) 4&gt;&amp;1`</i></font>
-<font color=GRAY>  17:</font> +<font color=GRAY>  17:</font>
 <font color=GRAY>  18:</font> <font color=DARKGREEN><i># In the subshell, run another subshell to execute ex13, and </i></font> <font color=GRAY>  18:</font> <font color=DARKGREEN><i># In the subshell, run another subshell to execute ex13, and </i></font>
 <font color=GRAY>  19:</font> <font color=DARKGREEN><i># echo the status code to 4</i></font> <font color=GRAY>  19:</font> <font color=DARKGREEN><i># echo the status code to 4</i></font>
  
 <font color=GRAY>  20:</font> <font color=DARKGREEN><i># (./ex13.sh; <font color=DARKBLUE>echo </font>$? &gt;&amp;4)</i></font> <font color=GRAY>  20:</font> <font color=DARKGREEN><i># (./ex13.sh; <font color=DARKBLUE>echo </font>$? &gt;&amp;4)</i></font>
-<font color=GRAY>  21:</font> +<font color=GRAY>  21:</font>
 <font color=GRAY>  22:</font> <font color=DARKGREEN><i># stdout from the inner subshell is directed to the original stdout (3)</i></font> <font color=GRAY>  22:</font> <font color=DARKGREEN><i># stdout from the inner subshell is directed to the original stdout (3)</i></font>
 <font color=GRAY>  23:</font> <font color=DARKGREEN><i># stderr is passed into the pipe for further processing.</i></font> <font color=GRAY>  23:</font> <font color=DARKGREEN><i># stderr is passed into the pipe for further processing.</i></font>
  
 <font color=GRAY>  24:</font> <font color=DARKGREEN><i># stdout from the pipe is redirected back to stderr</i></font> <font color=GRAY>  24:</font> <font color=DARKGREEN><i># stdout from the pipe is redirected back to stderr</i></font>
-<font color=GRAY>  25:</font> +<font color=GRAY>  25:</font>
 <font color=GRAY>  26:</font> <font color=DARKGREEN><i># Close the extra descriptors before running the commands</i></font> <font color=GRAY>  26:</font> <font color=DARKGREEN><i># Close the extra descriptors before running the commands</i></font>
 <font color=GRAY>  27:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1 <font color=GRAY>  27:</font> <font color=DARKBLUE>exec </font>3&gt;&amp;1
  
-<font color=GRAY>  28:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 2&gt;&amp;1 1&gt;&amp;3 3&gt;&amp;- 4&gt;&amp;- ; <font color=DARKBLUE>echo </font>$? &gt;&amp;4) | \+<font color=GRAY>  28:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 2&gt;&amp;1 1&gt;&amp;3 3&gt;&amp;- 4&gt;&amp;- ; <font color=DARKBLUE>echo </font>$? &gt;&amp;4) | \\
 <font color=GRAY>  29:</font>   sed s/err/ERR/ 1&gt;&amp;2 3&gt;&amp;- 4&gt;&amp;- ) 4&gt;&amp;1` <font color=GRAY>  29:</font>   sed s/err/ERR/ 1&gt;&amp;2 3&gt;&amp;- 4&gt;&amp;- ) 4&gt;&amp;1`
  
-<font color=GRAY>  30:</font> +<font color=GRAY>  30:</font>
 <font color=GRAY>  31:</font> <font color=DARKBLUE>echo </font>Last command status=$? <font color=GRAY>  31:</font> <font color=DARKBLUE>echo </font>Last command status=$?
 <font color=GRAY>  32:</font> <font color=DARKBLUE>echo </font>ex13stat=<font color=BLACK>$ex13stat</font> <font color=GRAY>  32:</font> <font color=DARKBLUE>echo </font>ex13stat=<font color=BLACK>$ex13stat</font>
-<font color=GRAY>  33:</font> +<font color=GRAY>  33:</font>
  
 </font></code> </font></code>
Line 2212: Line 2275:
 <p align=RIGHT class="newpage"><font size=-1>(26)</font></P> <p align=RIGHT class="newpage"><font size=-1>(26)</font></P>
  
-<font color=DARKBLUE><h1>Coprocesses and Background jobs</H1></font>+<font color=DARKBLUE>======Coprocesses and Background jobs</H1></font>
  
 Scripts can start any number of background jobs (any external command), Scripts can start any number of background jobs (any external command),
Line 2230: Line 2293:
 </DL> </DL>
  
-<h3>ksh coprocesses</h3>+====ksh coprocesses====
  
 <I>Coprocesses</I> are a way of starting a separate process which <I>Coprocesses</I> are a way of starting a separate process which
Line 2261: Line 2324:
 <code><font color=DARKRED> <code><font color=DARKRED>
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font>
-<font color=GRAY>   2:</font> +<font color=GRAY>   2:</font>
 <font color=GRAY>   3:</font> <font color=DARKGREEN><i># If we have not redirected standard output, save a copy of</i></font> <font color=GRAY>   3:</font> <font color=DARKGREEN><i># If we have not redirected standard output, save a copy of</i></font>
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i># the output of this script into a file, but still send a</i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i># the output of this script into a file, but still send a</i></font>
  
 <font color=GRAY>   5:</font> <font color=DARKGREEN><i># copy to the screen.</i></font> <font color=GRAY>   5:</font> <font color=DARKGREEN><i># copy to the screen.</i></font>
-<font color=GRAY>   6:</font> +<font color=GRAY>   6:</font>
 <font color=GRAY>   7:</font> <font color=DARKBLUE>if </font>[[ -t 1 ]] ; <font color=DARKBLUE>then</font> <font color=GRAY>   7:</font> <font color=DARKBLUE>if </font>[[ -t 1 ]] ; <font color=DARKBLUE>then</font>
 <font color=GRAY>   8:</font>   <font color=DARKGREEN><i># Only do this if fd 1 (stdout) is still connected</i></font> <font color=GRAY>   8:</font>   <font color=DARKGREEN><i># Only do this if fd 1 (stdout) is still connected</i></font>
  
 <font color=GRAY>   9:</font>   <font color=DARKGREEN><i># to a terminal</i></font> <font color=GRAY>   9:</font>   <font color=DARKGREEN><i># to a terminal</i></font>
-<font color=GRAY>  10:</font> +<font color=GRAY>  10:</font>
 <font color=GRAY>  11:</font>   <font color=DARKGREEN><i># We want the standard output of the "tee" process</i></font> <font color=GRAY>  11:</font>   <font color=DARKGREEN><i># We want the standard output of the "tee" process</i></font>
 <font color=GRAY>  12:</font>   <font color=DARKGREEN><i># to go explicitly to the screen (/dev/tty)</i></font> <font color=GRAY>  12:</font>   <font color=DARKGREEN><i># to go explicitly to the screen (/dev/tty)</i></font>
  
 <font color=GRAY>  13:</font>   <font color=DARKGREEN><i># and the second copy goes into a logfile named $0.out</i></font> <font color=GRAY>  13:</font>   <font color=DARKGREEN><i># and the second copy goes into a logfile named $0.out</i></font>
-<font color=GRAY>  14:</font> +<font color=GRAY>  14:</font>
 <font color=GRAY>  15:</font>   tee <font color=BLACK>$0</font>.out &gt;/dev/tty |&amp; <font color=GRAY>  15:</font>   tee <font color=BLACK>$0</font>.out &gt;/dev/tty |&amp;
-<font color=GRAY>  16:</font> +<font color=GRAY>  16:</font>
  
 <font color=GRAY>  17:</font>   <font color=DARKGREEN><i># Our stdout all goes into this coprocess</i></font> <font color=GRAY>  17:</font>   <font color=DARKGREEN><i># Our stdout all goes into this coprocess</i></font>
 <font color=GRAY>  18:</font>   <font color=DARKBLUE>exec </font>1&gt;&amp;p <font color=GRAY>  18:</font>   <font color=DARKBLUE>exec </font>1&gt;&amp;p
 <font color=GRAY>  19:</font> <font color=DARKBLUE>fi</font> <font color=GRAY>  19:</font> <font color=DARKBLUE>fi</font>
-<font color=GRAY>  20:</font> +<font color=GRAY>  20:</font>
  
 <font color=GRAY>  21:</font> <font color=DARKGREEN><i># Now generate some output</i></font> <font color=GRAY>  21:</font> <font color=DARKGREEN><i># Now generate some output</i></font>
Line 2305: Line 2368:
 <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font> <font color=GRAY>   1:</font> <font color=DARKGREEN><i>#!/bin/ksh</i></font>
 <font color=GRAY>   2:</font> <font color=DARKGREEN><i># This example uses a locally written tool for Dartmouth Name Directory lookups</i></font> <font color=GRAY>   2:</font> <font color=DARKGREEN><i># This example uses a locally written tool for Dartmouth Name Directory lookups</i></font>
-<font color=GRAY>   3:</font> +<font color=GRAY>   3:</font>
 <font color=GRAY>   4:</font> <font color=DARKGREEN><i># Start the dndlookup program as a coprocess</i></font> <font color=GRAY>   4:</font> <font color=DARKGREEN><i># Start the dndlookup program as a coprocess</i></font>
  
 <font color=GRAY>   5:</font> <font color=DARKGREEN><i># Tell it to output only the canonical full name, and to not print multiple matches</i></font> <font color=GRAY>   5:</font> <font color=DARKGREEN><i># Tell it to output only the canonical full name, and to not print multiple matches</i></font>
 <font color=GRAY>   6:</font> dndlookup -fname -u |&amp; <font color=GRAY>   6:</font> dndlookup -fname -u |&amp;
-<font color=GRAY>   7:</font> +<font color=GRAY>   7:</font>
 <font color=GRAY>   8:</font> <font color=DARKGREEN><i># move the input/output streams so we </i></font> <font color=GRAY>   8:</font> <font color=DARKGREEN><i># move the input/output streams so we </i></font>
  
Line 2317: Line 2380:
 <font color=GRAY>  11:</font> <font color=DARKBLUE>exec </font>5&lt;&amp;p <font color=GRAY>  11:</font> <font color=DARKBLUE>exec </font>5&lt;&amp;p
  
-<font color=GRAY>  12:</font> +<font color=GRAY>  12:</font>
 <font color=GRAY>  13:</font> <font color=DARKBLUE>echo </font>"Name file contents:" <font color=GRAY>  13:</font> <font color=DARKBLUE>echo </font>"Name file contents:"
 <font color=GRAY>  14:</font> cat namefile <font color=GRAY>  14:</font> cat namefile
 <font color=GRAY>  15:</font> <font color=DARKBLUE>echo</font> <font color=GRAY>  15:</font> <font color=DARKBLUE>echo</font>
  
-<font color=GRAY>  16:</font> +<font color=GRAY>  16:</font>
 <font color=GRAY>  17:</font> <font color=DARKGREEN><i># read the names from a file "namefile"</i></font> <font color=GRAY>  17:</font> <font color=DARKGREEN><i># read the names from a file "namefile"</i></font>
 <font color=GRAY>  18:</font> <font color=DARKBLUE>while </font>read uname; <font color=DARKBLUE>do</font> <font color=GRAY>  18:</font> <font color=DARKBLUE>while </font>read uname; <font color=DARKBLUE>do</font>
Line 2329: Line 2392:
 <font color=GRAY>  20:</font>   <font color=DARKBLUE>read </font> -u5 dndname <font color=GRAY>  20:</font>   <font color=DARKBLUE>read </font> -u5 dndname
 <font color=GRAY>  21:</font>   <font color=DARKBLUE>case </font><font color=BLACK>$dndname</font> in <font color=GRAY>  21:</font>   <font color=DARKBLUE>case </font><font color=BLACK>$dndname</font> in
-<font color=GRAY>  22:</font>   *many\ matches*)+<font color=GRAY>  22:</font>   *many\\ matches*)
  
 <font color=GRAY>  23:</font>     <font color=DARKGREEN><i># handle case where the name wasn't unique</i></font> <font color=GRAY>  23:</font>     <font color=DARKGREEN><i># handle case where the name wasn't unique</i></font>
-<font color=GRAY>  24:</font>     <font color=DARKBLUE>print </font>"Multiple matches to \"<font color=BLACK>$uname</font>\" in DND"+<font color=GRAY>  24:</font>     <font color=DARKBLUE>print </font>"Multiple matches to \\"<font color=BLACK>$uname</font>\\" in DND"
 <font color=GRAY>  25:</font>     ;; <font color=GRAY>  25:</font>     ;;
-<font color=GRAY>  26:</font>   *no\ match*)+<font color=GRAY>  26:</font>   *no\\ match*)
  
 <font color=GRAY>  27:</font>     <font color=DARKGREEN><i># handle case where the name wasn't found</i></font> <font color=GRAY>  27:</font>     <font color=DARKGREEN><i># handle case where the name wasn't found</i></font>
-<font color=GRAY>  28:</font>     <font color=DARKBLUE>print </font>"No matches to \"<font color=BLACK>$uname</font>\" in DND"+<font color=GRAY>  28:</font>     <font color=DARKBLUE>print </font>"No matches to \\"<font color=BLACK>$uname</font>\\" in DND"
 <font color=GRAY>  29:</font>     ;; <font color=GRAY>  29:</font>     ;;
 <font color=GRAY>  30:</font>   *) <font color=GRAY>  30:</font>   *)
Line 2343: Line 2406:
 <font color=GRAY>  31:</font>     <font color=DARKGREEN><i># we seem to have a hit - process the</i></font> <font color=GRAY>  31:</font>     <font color=DARKGREEN><i># we seem to have a hit - process the</i></font>
 <font color=GRAY>  32:</font>     <font color=DARKGREEN><i># canonical named retrieved from dndlookup</i></font> <font color=GRAY>  32:</font>     <font color=DARKGREEN><i># canonical named retrieved from dndlookup</i></font>
-<font color=GRAY>  33:</font>     <font color=DARKBLUE>print </font>"Unique DND match: full name for \"<font color=BLACK>$uname</font>\" is \"<font color=BLACK>$dndname</font>\""+<font color=GRAY>  33:</font>     <font color=DARKBLUE>print </font>"Unique DND match: full name for \\"<font color=BLACK>$uname</font>\\" is \\"<font color=BLACK>$dndname</font>\\""
  
-<font color=GRAY>  34:</font>     ;; +<font color=GRAY>  34:</font>     ;;
 <font color=GRAY>  35:</font>   <font color=DARKBLUE>esac</font> <font color=GRAY>  35:</font>   <font color=DARKBLUE>esac</font>
 <font color=GRAY>  36:</font>   sleep 2 <font color=GRAY>  36:</font>   sleep 2
 <font color=GRAY>  37:</font> <font color=DARKBLUE>done </font>&lt; namefile <font color=GRAY>  37:</font> <font color=DARKBLUE>done </font>&lt; namefile
  
-<font color=GRAY>  38:</font> +<font color=GRAY>  38:</font>
 <font color=GRAY>  39:</font> <font color=DARKGREEN><i># We've read all the names, but the coprocess</i></font> <font color=GRAY>  39:</font> <font color=DARKGREEN><i># We've read all the names, but the coprocess</i></font>
 <font color=GRAY>  40:</font> <font color=DARKGREEN><i># is still running.  Close the pipe to tell it</i></font> <font color=GRAY>  40:</font> <font color=DARKGREEN><i># is still running.  Close the pipe to tell it</i></font>
Line 2368: Line 2431:
  
 <p align=RIGHT class="newpage"><font size=-1>(27)</font></P> <p align=RIGHT class="newpage"><font size=-1>(27)</font></P>
-<font color=DARKBLUE><h1>Variable arrays</H1></font>+<font color=DARKBLUE>======Variable arrays</H1></font>
  
 Both ksh and bash implement arrays of variables, but in somewhat different ways. Both ksh and bash implement arrays of variables, but in somewhat different ways.
Line 2402: Line 2465:
 <font color=GRAY>   9:</font> <font color=DARKGREEN><i>#  -u user -- filter for the named user before translating addresses</i></font> <font color=GRAY>   9:</font> <font color=DARKGREEN><i>#  -u user -- filter for the named user before translating addresses</i></font>
  
-<font color=GRAY>  10:</font> +<font color=GRAY>  10:</font>
 <font color=GRAY>  11:</font> hextodec() <font color=GRAY>  11:</font> hextodec()
 <font color=GRAY>  12:</font> { <font color=GRAY>  12:</font> {
Line 2409: Line 2472:
  
 <font color=GRAY>  15:</font> } <font color=GRAY>  15:</font> }
-<font color=GRAY>  16:</font> +<font color=GRAY>  16:</font>
 <font color=GRAY>  17:</font> hostlookup() <font color=GRAY>  17:</font> hostlookup()
 <font color=GRAY>  18:</font> { <font color=GRAY>  18:</font> {
Line 2416: Line 2479:
 <font color=GRAY>  20:</font>    <font color=BLACK>hostname=</font>$(<font color=PURPLE>host <font color=BLACK>$1</font></font>) <font color=GRAY>  20:</font>    <font color=BLACK>hostname=</font>$(<font color=PURPLE>host <font color=BLACK>$1</font></font>)
 <font color=GRAY>  21:</font>    <font color=DARKBLUE>case </font><font color=BLACK>$hostname</font> in <font color=GRAY>  21:</font>    <font color=DARKBLUE>case </font><font color=BLACK>$hostname</font> in
-<font color=GRAY>  22:</font>    *\ not\ found*)+<font color=GRAY>  22:</font>    *\\ not\\ found*)
  
 <font color=GRAY>  23:</font>       <font color=DARKGREEN><i># Just echo the address we tried to look up</i></font> <font color=GRAY>  23:</font>       <font color=DARKGREEN><i># Just echo the address we tried to look up</i></font>
Line 2430: Line 2493:
 <font color=GRAY>  31:</font>    <font color=DARKBLUE>esac</font> <font color=GRAY>  31:</font>    <font color=DARKBLUE>esac</font>
 <font color=GRAY>  32:</font> } <font color=GRAY>  32:</font> }
-<font color=GRAY>  33:</font> +<font color=GRAY>  33:</font>
 <font color=GRAY>  34:</font> <font color=DARKGREEN><i># Options</i></font> <font color=GRAY>  34:</font> <font color=DARKGREEN><i># Options</i></font>
  
Line 2447: Line 2510:
 <font color=GRAY>  45:</font> <font color=DARKBLUE>shift </font><font color=DARKBLUE>$((<font color=BLACK>$OPTIND</font>-1))</font> <font color=GRAY>  45:</font> <font color=DARKBLUE>shift </font><font color=DARKBLUE>$((<font color=BLACK>$OPTIND</font>-1))</font>
  
-<font color=GRAY>  46:</font> +<font color=GRAY>  46:</font>
 <font color=GRAY>  47:</font> <font color=DARKGREEN><i># We could get the DB server names from 'fs checkservers', but it isn't obvious what is from our cell.  We</i></font> <font color=GRAY>  47:</font> <font color=DARKGREEN><i># We could get the DB server names from 'fs checkservers', but it isn't obvious what is from our cell.  We</i></font>
 <font color=GRAY>  48:</font> <font color=DARKGREEN><i># could also grep CellServDB.  I cop out and hard code one known DB server and get the others from it.</i></font> <font color=GRAY>  48:</font> <font color=DARKGREEN><i># could also grep CellServDB.  I cop out and hard code one known DB server and get the others from it.</i></font>
Line 2453: Line 2516:
  
 <font color=GRAY>  50:</font> <font color=BLACK>serverlist=</font>$(<font color=PURPLE>bos listhosts -server <font color=BLACK>$masterserver</font>| grep 'Host .* is ' | awk '{print <font color=BLACK>$4</font>}'</font>) <font color=GRAY>  50:</font> <font color=BLACK>serverlist=</font>$(<font color=PURPLE>bos listhosts -server <font color=BLACK>$masterserver</font>| grep 'Host .* is ' | awk '{print <font color=BLACK>$4</font>}'</font>)
-<font color=GRAY>  51:</font> +<font color=GRAY>  51:</font>
 <font color=GRAY>  52:</font> <font color=DARKGREEN><i># If we want to filter usernames, it is more efficient to do it inline, before sorting, translation and hostname lookups</i></font> <font color=GRAY>  52:</font> <font color=DARKGREEN><i># If we want to filter usernames, it is more efficient to do it inline, before sorting, translation and hostname lookups</i></font>
  
-<font color=GRAY>  53:</font> +<font color=GRAY>  53:</font>
 <font color=GRAY>  54:</font> <font color=DARKGREEN><i># Array to hold IP address/name conversions (associative array, ksh only)</i></font> <font color=GRAY>  54:</font> <font color=DARKGREEN><i># Array to hold IP address/name conversions (associative array, ksh only)</i></font>
 <font color=GRAY>  55:</font> <font color=DARKGREEN><i># ksh - use -A for associative array.  bash - use -a and numeric array</i></font> <font color=GRAY>  55:</font> <font color=DARKGREEN><i># ksh - use -A for associative array.  bash - use -a and numeric array</i></font>
 <font color=GRAY>  56:</font> <font color=DARKBLUE>typeset </font>-a hostnames <font color=GRAY>  56:</font> <font color=DARKBLUE>typeset </font>-a hostnames
  
-<font color=GRAY>  57:</font> +<font color=GRAY>  57:</font>
 <font color=GRAY>  58:</font> ( <font color=GRAY>  58:</font> (
 <font color=GRAY>  59:</font> <font color=DARKBLUE>for </font>dbserver in <font color=BLACK>$serverlist</font>; <font color=DARKBLUE>do</font> <font color=GRAY>  59:</font> <font color=DARKBLUE>for </font>dbserver in <font color=BLACK>$serverlist</font>; <font color=DARKBLUE>do</font>
Line 2467: Line 2530:
  
 <font color=GRAY>  61:</font> <font color=DARKBLUE>done</font> <font color=GRAY>  61:</font> <font color=DARKBLUE>done</font>
-<font color=GRAY>  62:</font> ) | grep -v 'Fetching log file' | <font color=BLACK>$filter</font> | sed -e 's/^... //' -e 's/  \([1-9]\) / 0\1 /' | sort --month-sort | \ +<font color=GRAY>  62:</font> ) | grep -v 'Fetching log file' | <font color=BLACK>$filter</font> | sed -e 's/^... //' -e 's/  \\([[1-9]]\\) / 0\\1 /' | sort --month-sort | \
-<font color=GRAY>  63:</font>     sed '-e s/ \([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\)$/ 0\1/' |+<font color=GRAY>  63:</font>     sed '-e s/ \\([[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]]\\)$/ 0\\1/' |
 <font color=GRAY>  64:</font>     <font color=DARKBLUE>while </font>read line; <font color=DARKBLUE>do</font> <font color=GRAY>  64:</font>     <font color=DARKBLUE>while </font>read line; <font color=DARKBLUE>do</font>
  
Line 2477: Line 2540:
 <font color=GRAY>  68:</font>       <font color=DARKGREEN><i># The second 'sed' in the pipe catches these are fixes them.</i></font> <font color=GRAY>  68:</font>       <font color=DARKGREEN><i># The second 'sed' in the pipe catches these are fixes them.</i></font>
 <font color=GRAY>  69:</font>       <font color=DARKBLUE>case </font><font color=BLACK>$line</font> in <font color=GRAY>  69:</font>       <font color=DARKBLUE>case </font><font color=BLACK>$line</font> in
-<font color=GRAY>  70:</font>       *\ from\ [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])+<font color=GRAY>  70:</font>       *\\ from\\ [[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]][[0-9a-f]])
 <font color=GRAY>  71:</font>          <font color=DARKGREEN><i># translate the reverse-hex address</i></font> <font color=GRAY>  71:</font>          <font color=DARKGREEN><i># translate the reverse-hex address</i></font>
  
Line 2490: Line 2553:
 <font color=GRAY>  78:</font>             <font color=DARKGREEN><i># bash - index on numeric value (ipdec)</i></font> <font color=GRAY>  78:</font>             <font color=DARKGREEN><i># bash - index on numeric value (ipdec)</i></font>
 <font color=GRAY>  79:</font>             <font color=BLACK>index=</font><font color=BLACK>$ipdec</font> <font color=GRAY>  79:</font>             <font color=BLACK>index=</font><font color=BLACK>$ipdec</font>
-<font color=GRAY>  80:</font>             <font color=DARKBLUE>if </font>[[ -z "<font color=BLACK>${hostnames[<font color=BLACK>$index</font>]}</font>" ]]; <font color=DARKBLUE>then</font>+<font color=GRAY>  80:</font>             <font color=DARKBLUE>if </font>[[ -z "<font color=BLACK>${hostnames[[<font color=BLACK>$index</font>]]}</font>" ]]; <font color=DARKBLUE>then</font>
  
-<font color=GRAY>  81:</font>                hostnames[<font color=BLACK>$index</font>]="$(<font color=PURPLE>hostlookup $(hextodec <font color=BLACK>$iphex</font>)</font>)" +<font color=GRAY>  81:</font>                hostnames[[<font color=BLACK>$index</font>]]="$(<font color=PURPLE>hostlookup $(hextodec <font color=BLACK>$iphex</font>)</font>)"
 <font color=GRAY>  82:</font>             <font color=DARKBLUE>fi</font> <font color=GRAY>  82:</font>             <font color=DARKBLUE>fi</font>
-<font color=GRAY>  83:</font>             <font color=DARKBLUE>echo </font>"<font color=BLACK>$frontpart</font> from <font color=BLACK>${hostnames[<font color=BLACK>$index</font>]}</font>"+<font color=GRAY>  83:</font>             <font color=DARKBLUE>echo </font>"<font color=BLACK>$frontpart</font> from <font color=BLACK>${hostnames[[<font color=BLACK>$index</font>]]}</font>"
  
 <font color=GRAY>  84:</font>          <font color=DARKBLUE>else</font> <font color=GRAY>  84:</font>          <font color=DARKBLUE>else</font>
Line 2510: Line 2573:
 <font color=GRAY>  94:</font>       <font color=DARKBLUE>echo </font>"<font color=BLACK>$line</font>" <font color=GRAY>  94:</font>       <font color=DARKBLUE>echo </font>"<font color=BLACK>$line</font>"
  
-<font color=GRAY>  95:</font>    <font color=DARKBLUE>fi </font>  +<font color=GRAY>  95:</font>    <font color=DARKBLUE>fi </font>
 <font color=GRAY>  96:</font> <font color=DARKBLUE>done</font> <font color=GRAY>  96:</font> <font color=DARKBLUE>done</font>
-<font color=GRAY>  97:</font> +<font color=GRAY>  97:</font>
 </font></code> </font></code>
  
Line 2524: Line 2587:
  
 <p align=RIGHT class="newpage"><font size=-1>(28)</font></P> <p align=RIGHT class="newpage"><font size=-1>(28)</font></P>
-<font color=DARKBLUE><h1>Delivering and Trapping Signals</H1></font>+<font color=DARKBLUE>======Delivering and Trapping Signals</H1></font>
  
 Unix signals (software interrupts) can be sent as asynchronous events to shell scripts, just Unix signals (software interrupts) can be sent as asynchronous events to shell scripts, just
Line 2531: Line 2594:
 program.  This is often used to perform clean-up actions before exiting, or restart certain program.  This is often used to perform clean-up actions before exiting, or restart certain
 procedures.  Execution resumes where it left off, if the signal handler returns.  Signal traps procedures.  Execution resumes where it left off, if the signal handler returns.  Signal traps
-must be set separately inside of shell functions.  Signals can be sent to a process with +must be set separately inside of shell functions.  Signals can be sent to a process with
 <a href="http://www.FreeBSD.org/cgi/man.cgi?query=kill&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>kill</code></b></font></a>. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=kill&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>kill</code></b></font></a>.
  
Line 2564: Line 2627:
 <font color=GRAY>   2:</font> <font color=DARKGREEN><i># Try this under bash, ksh and sh</i></font> <font color=GRAY>   2:</font> <font color=DARKGREEN><i># Try this under bash, ksh and sh</i></font>
  
-<font color=GRAY>   3:</font> +<font color=GRAY>   3:</font>
 <font color=GRAY>   4:</font> <font color=DARKBLUE>trap </font>huphandler  HUP <font color=GRAY>   4:</font> <font color=DARKBLUE>trap </font>huphandler  HUP
-<font color=GRAY>   5:</font> <font color=DARKBLUE>trap </font>''          QUIT+<font color=GRAY>   5:</font> <font color=DARKBLUE>trap </font>//          QUIT
 <font color=GRAY>   6:</font> <font color=DARKBLUE>trap </font>exithandler TERM INT <font color=GRAY>   6:</font> <font color=DARKBLUE>trap </font>exithandler TERM INT
  
-<font color=GRAY>   7:</font> +<font color=GRAY>   7:</font>
 <font color=GRAY>   8:</font> huphandler() <font color=GRAY>   8:</font> huphandler()
 <font color=GRAY>   9:</font> { <font color=GRAY>   9:</font> {
Line 2576: Line 2639:
  
 <font color=GRAY>  12:</font> } <font color=GRAY>  12:</font> }
-<font color=GRAY>  13:</font> +<font color=GRAY>  13:</font>
 <font color=GRAY>  14:</font> exithandler() <font color=GRAY>  14:</font> exithandler()
 <font color=GRAY>  15:</font> { <font color=GRAY>  15:</font> {
Line 2587: Line 2650:
  
 <font color=GRAY>  21:</font> <font color=DARKGREEN><i># SECONDS is built-in to bash and ksh.  It is number of seconds since script started</i></font> <font color=GRAY>  21:</font> <font color=DARKGREEN><i># SECONDS is built-in to bash and ksh.  It is number of seconds since script started</i></font>
-<font color=GRAY>  22:</font> <font color=DARKBLUE></font>is like a comment, but it is evaluated for side effects and evaluates to true+<font color=GRAY>  22:</font> <font color=DARKBLUE></font>is like a comment, but it is evaluated for side effects and evaluates to true
 <font color=GRAY>  23:</font> <font color=BLACK>seconds=</font>0 <font color=GRAY>  23:</font> <font color=BLACK>seconds=</font>0
-<font color=GRAY>  24:</font> <font color=DARKBLUE>while </font>; <font color=DARKBLUE>do</font>+<font color=GRAY>  24:</font> <font color=DARKBLUE>while </font>; <font color=DARKBLUE>do</font>
  
 <font color=GRAY>  25:</font> <font color=DARKGREEN><i># while true; do</i></font> <font color=GRAY>  25:</font> <font color=DARKGREEN><i># while true; do</i></font>
Line 2612: Line 2675:
  
 <p align=RIGHT class="newpage"><font size=-1>(29)</font></P> <p align=RIGHT class="newpage"><font size=-1>(29)</font></P>
-<font color=DARKBLUE><h1>Security issues in shell scripts</H1></font>+<font color=DARKBLUE>======Security issues in shell scripts</H1></font>
  
 Shell scripts are often used by system administrators and are run as a priviledged user. Shell scripts are often used by system administrators and are run as a priviledged user.
Line 2618: Line 2681:
  
 <UL> <UL>
-<LI>Don't use set-UID scripts. +<LI>Don't use set-UID scripts.
 <blockquote><small> <blockquote><small>
 Most systems don't even allow a script to be made set-UID.  It is Most systems don't even allow a script to be made set-UID.  It is
-impossible (due to inherent race conditions) to ensure that a set-uid script cannot be compromised.  +impossible (due to inherent race conditions) to ensure that a set-uid script cannot be compromised.
 Use wrapper programs like <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sudo&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sudo</code></b></font></a> instead. Use wrapper programs like <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sudo&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sudo</code></b></font></a> instead.
 </small></blockquote> </small></blockquote>
Line 2628: Line 2691:
 which external programs will be used. which external programs will be used.
 <P> <P>
-<LI>If possible, don't use temporary files.  If they cannot be avoided, use <font color=DARKRED><b><code>$TMPDIR</code></b></font>,  +<LI>If possible, don't use temporary files.  If they cannot be avoided, use <font color=DARKRED><b><code>$TMPDIR</code></b></font>,
 and create files safely (e.g. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=mktemp&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>mktemp</code></b></font></a>). and create files safely (e.g. <a href="http://www.FreeBSD.org/cgi/man.cgi?query=mktemp&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>mktemp</code></b></font></a>).
  
 <blockquote><small> <blockquote><small>
-Often scripts will write to a fixed, or trivially generated temporary filename in /tmp.  If the +Often scripts will write to a fixed, or trivially generated temporary filename in /tmp.  If the
 file already exists and you don't have permission to overwrite it, the script will fail.  If you file already exists and you don't have permission to overwrite it, the script will fail.  If you
 do have permission to overwrite it, you will delete the previous contents.  Since /tmp is public write, do have permission to overwrite it, you will delete the previous contents.  Since /tmp is public write,
Line 2640: Line 2703:
 <OL> <OL>
 <LI>A link is created by an unprivileged user in /tmp: <font color=DARKRED><b><code> /tmp/scratch  -> /vmunix</code></b></font> <LI>A link is created by an unprivileged user in /tmp: <font color=DARKRED><b><code> /tmp/scratch  -> /vmunix</code></b></font>
-<LI>A root user runs a script that blindly writes a scratch file to /tmp/scratch, and overwrites the +<LI>A root user runs a script that blindly writes a scratch file to /tmp/scratch, and overwrites the
 operating system. operating system.
 </OL> </OL>
Line 2658: Line 2721:
 tmp=$tmp/tempdir.$RANDOM.$RANDOM.$RANDOM.$$ tmp=$tmp/tempdir.$RANDOM.$RANDOM.$RANDOM.$$
 (umask 077 && mkdir $tmp) || { (umask 077 && mkdir $tmp) || {
 +<code>
     echo "Could not create temporary directory" 1>&2     echo "Could not create temporary directory" 1>&2
     exit 1     exit 1
 +</code>
 } }
 </PRE> </PRE>
Line 2671: Line 2736:
 <LI>Don't trust user input <LI>Don't trust user input
 <UL> <UL>
 +<code>
   <LI>contents of files   <LI>contents of files
   <LI>data piped from other programs   <LI>data piped from other programs
-  <LI>file <EM>names</EM> Output of filename generation with wildcards, or directly from +  <LI>file <EM>names</EM> Output of filename generation with wildcards, or directly from
      <font color=DARKRED><b><code>ls</code></b></font> or <font color=DARKRED><b><code>find</code></b></font>      <font color=DARKRED><b><code>ls</code></b></font> or <font color=DARKRED><b><code>find</code></b></font>
 +</code>
  
 </UL> </UL>
Line 2681: Line 2748:
 <I>Example:</I> <I>Example:</I>
 <BR> <BR>
-Consider the effects of a file named "<font color=DARKRED><b><code>myfile;cd /;rm *</code></b></font>" if processed, +Consider the effects of a file named "<font color=DARKRED><b><code>myfile;cd /;rm *</code></b></font>" if processed,
 unquoted, by your script. unquoted, by your script.
 <blockquote><small> <blockquote><small>
 One possible way to protect against weirdo characters in file names: One possible way to protect against weirdo characters in file names:
 <PRE> <PRE>
-  - A function to massage a list of filenames  +  -  A function to massage a list of filenames 
-  - to protect weirdo characters +  -  to protect weirdo characters 
-  - e.g. find ... | protect_filenames | xargs command +  -  e.g. find ... | protect_filenames | xargs command 
-# +   
-  - We are backslash-protecting the characters \'" ?*;+  -  We are backslash-protecting the characters \\'" ?*;
 protect_filenames() protect_filenames()
 { {
-   sed -es/\\\\/\\\\\\\\/g \ +<code> 
-       -es/\\\'/\\\\\'/  \ +   sed -es/\\\\\\\\/\\\\\\\\\\\\\\\\/\
-       -es/\\\"/\\\\\"/  \ +       -es/\\\\\\'/\\\\\\\\\\'/  \
-       -es/\\\;/\\\\\;/  \ +       -es/\\\\\\"/\\\\\\\\\\"/  \
-       -es/\\\?/\\\\\?/  \ +       -es/\\\\\\;/\\\\\\\\\\;/  \
-       -es/\\\*/\\\\\*/  \ +       -es/\\\\\\?/\\\\\\\\\\?/  \
-       -es/\\\ /\\\\\ /g+       -es/\\\\\\*/\\\\\\\\\\*/  \
 +       -es/\\\\\\ /\\\\\\\\\\ /g 
 +</code>
 } }
 </PRE> </PRE>
Line 2715: Line 2784:
  
 <p align=RIGHT class="newpage"><font size=-1>(30)</font></P> <p align=RIGHT class="newpage"><font size=-1>(30)</font></P>
-<font color=DARKBLUE><h1>Style</H1></font>+<font color=DARKBLUE>======Style</H1></font>
  
 Shell scripts are very frequently written quickly for a single purpose, used once and discarded. Shell scripts are very frequently written quickly for a single purpose, used once and discarded.
 They are also as frequently kept and used many times, and migrate into other uses, but often They are also as frequently kept and used many times, and migrate into other uses, but often
-do not receive the same level of testing and debugging that other software would be given +do not receive the same level of testing and debugging that other software would be given
 in the same situation.  It <EM>is</EM> possible to apply general principles of good software in the same situation.  It <EM>is</EM> possible to apply general principles of good software
 engineering to shell scripts. engineering to shell scripts.
Line 2729: Line 2798:
 <LI>Document any non-standard external utilities which your script needs <LI>Document any non-standard external utilities which your script needs
 <LI>Document your scripts with inline comments - you'll need them in a few months when you edit it. <LI>Document your scripts with inline comments - you'll need them in a few months when you edit it.
-<LI>Treat standard input and output in the normal way, so that your script can be used +<LI>Treat standard input and output in the normal way, so that your script can be used
 in combination with other programs (the Unix toolkit philosophy) in combination with other programs (the Unix toolkit philosophy)
 <LI>Be consistent in the format of your output, so that other programs can rely on it <LI>Be consistent in the format of your output, so that other programs can rely on it
Line 2740: Line 2809:
 </UL> </UL>
  
-<h2>When not to use shell scripts</h2>+=====When not to use shell scripts=====
  
 <UL> <UL>
 <LI>If an existing tool already does what you need - use it. <LI>If an existing tool already does what you need - use it.
-<LI>If the script is more than a few hundred lines, you are probably using the wrong tool.  +<LI>If the script is more than a few hundred lines, you are probably using the wrong tool.
 <LI>If performance is horrible, and the script is used a lot, you might want to consider another language. <LI>If performance is horrible, and the script is used a lot, you might want to consider another language.
 </UL> </UL>
Line 2756: Line 2825:
 <p align=RIGHT class="newpage"><font size=-1>(31)</font></P> <p align=RIGHT class="newpage"><font size=-1>(31)</font></P>
  
-<font color=DARKBLUE><h1>Some longer examples</H1></font>+<font color=DARKBLUE>======Some longer examples</H1></font>
  
 The class accounts have directories with all of the examples from the books by Blinn, The class accounts have directories with all of the examples from the books by Blinn,
Line 2770: Line 2839:
  
 <P> <P>
-<LI><B>checkpath</B> <A HREF=checkpath.html TARGET=example>display</A>, +<LI><B>checkpath</B> <A HREF=checkpath.html TARGET=example>display</A>,
 <A HREF=checkpath.txt TARGET=example>text</A><BR> <A HREF=checkpath.txt TARGET=example>text</A><BR>
 Check all the directories in the <font color=DARKRED><b><code>$PATH</code></b></font> for possibly conflicting programs. Check all the directories in the <font color=DARKRED><b><code>$PATH</code></b></font> for possibly conflicting programs.
Line 2796: Line 2865:
 This entire tutorial was created from individual HTML pages using a content management system written This entire tutorial was created from individual HTML pages using a content management system written
 as ksh scripts (heavily using sed to edit the pages), coordinated by <a href="http://www.FreeBSD.org/cgi/man.cgi?query=make&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>make</code></b></font></a>. as ksh scripts (heavily using sed to edit the pages), coordinated by <a href="http://www.FreeBSD.org/cgi/man.cgi?query=make&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>make</code></b></font></a>.
-<!-- +<!--
 <UL> <UL>
 <P> <P>
Line 2816: Line 2885:
 --> -->
 <P> <P>
-You can even write an entire web server as a shell script.  This one is part of the +You can even write an entire web server as a shell script.  This one is part of the
 <A HREF="http://www.nisi.ab.ca/lrp/" TARGET=_blank>LEAF</A> <A HREF="http://www.nisi.ab.ca/lrp/" TARGET=_blank>LEAF</A>
  
 (Linux Embedded Appliance Firewall) project.  This wouldn't be suitable for much load, but handles occasional queries on (Linux Embedded Appliance Firewall) project.  This wouldn't be suitable for much load, but handles occasional queries on
-static HTML and CGI scripts. +static HTML and CGI scripts.
 <a href="http://www.nisi.ab.ca/lrp/Packages/weblet.htm" TARGET=_blank>(www.nisi.ab.ca/lrp/Packages/weblet.htm)</a> <a href="http://www.nisi.ab.ca/lrp/Packages/weblet.htm" TARGET=_blank>(www.nisi.ab.ca/lrp/Packages/weblet.htm)</a>
 <UL> <UL>
Line 2833: Line 2902:
  
 <p align=RIGHT class="newpage"><font size=-1>(32)</font></P> <p align=RIGHT class="newpage"><font size=-1>(32)</font></P>
-<font color=DARKBLUE><h1>A Toolkit of commonly used external commands</H1></font>+<font color=DARKBLUE>======A Toolkit of commonly used external commands</H1></font>
  
 The following commands are very frequently used in shell scripts.  Many of them are used The following commands are very frequently used in shell scripts.  Many of them are used
Line 2842: Line 2911:
 data from standard input if no files are named. data from standard input if no files are named.
  
-<h3>Listing, copying and moving files and directories</h3>+====Listing, copying and moving files and directories====
  
 <DL> <DL>
Line 2868: Line 2937:
 </DL> </DL>
  
-<h3>Displaying text, files or parts of files</h3>+====Displaying text, files or parts of files====
  
 <DL> <DL>
Line 2878: Line 2947:
 Conflicts Conflicts
 sometimes arise over the syntax for echoing a line with no trailing CR/LF. sometimes arise over the syntax for echoing a line with no trailing CR/LF.
-Some use "\c" and some use option "-n" To avoid these problems, ksh also provides the "print"+Some use "\\c" and some use option "-n" To avoid these problems, ksh also provides the "print"
 command for output. command for output.
 </small></blockquote> </small></blockquote>
Line 2898: Line 2967:
 </DL> </DL>
  
-<h3>Compression and archiving</h3>+====Compression and archiving====
  
 <DL> <DL>
Line 2908: Line 2977:
 </DL> </DL>
  
-<h3>Sorting and searching for patterns</h3>+====Sorting and searching for patterns====
  
 <DL> <DL>
Line 2931: Line 3000:
 </DL> </DL>
  
-<h3>System information (users, processes, time)</h3>+====System information (users, processes, time)====
  
 <DL> <DL>
Line 2937: Line 3006:
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=date&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>date</code></b></font></a> <FONT COLOR=GREEN>*</FONT> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=date&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>date</code></b></font></a> <FONT COLOR=GREEN>*</FONT>
  
-<DD>Display the current date and time (flexible format).  Useful for conditional execution based on +<DD>Display the current date and time (flexible format).  Useful for conditional execution based on
 time, and for timestamping output. time, and for timestamping output.
  
Line 2970: Line 3039:
 </DL> </DL>
  
-<h3>Conditional tests</h3>+====Conditional tests====
  
 <DL> <DL>
  
-<DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=test&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>test</code></b></font></a>; <font color=DARKRED><b><code>[[</code></b></font>|<FONT COLOR=GREEN>*</FONT>+<DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=test&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>test</code></b></font></a>; <font color=DARKRED><b><code>[[</code></b></font> <FONT COLOR=GREEN>*</FONT>
 <DD>The conditional test, used extensively in scripts, is also an external program which evaluates <DD>The conditional test, used extensively in scripts, is also an external program which evaluates
-the expression given as an argument and returns true (0) or false (1) exit status.  The name "[" is a+the expression given as an argument and returns true (0) or false (1) exit status.  The name "[[" is a
 link to the "test" program, so a line like:<BR> link to the "test" program, so a line like:<BR>
-<font color=DARKRED><b><code>if [ -w logfile ]] </code></b></font><BR> +<font color=DARKRED><b><code>if [[ -w logfile ]] </code></b></font><BR> 
-actually runs a program "[[",|with arguments "-w logfile ]]", and returns a true/false value to the "if"+actually runs a program "[[", with arguments "-w logfile ]]", and returns a true/false value to the "if"
 command. command.
  
 <blockquote><small> <blockquote><small>
-In ksh and most newer versions of sh, "[["|is replaced with a compatible internal command, but the+In ksh and most newer versions of sh, "[[" is replaced with a compatible internal command, but the
 argument parsing is performed as if it were an external command. argument parsing is performed as if it were an external command.
 Ksh also provides the internal "[[" operator, with simplified syntax. Ksh also provides the internal "[[" operator, with simplified syntax.
Line 2990: Line 3059:
 </DL> </DL>
  
-<h3>Stream Editing</h3>+====Stream Editing====
  
 <DL> <DL>
Line 3017: Line 3086:
 </DL> </DL>
  
-<h3>Finding and comparing files</h3>+====Finding and comparing files====
  
 <DL> <DL>
Line 3047: Line 3116:
 </DL> </DL>
  
-<h3>Arithmetic and String Manipulation</h3>+====Arithmetic and String Manipulation====
  
 <DL> <DL>
Line 3055: Line 3124:
 returns a result to stdout.  The original Bourne shell had no built-in arithmetic operators. returns a result to stdout.  The original Bourne shell had no built-in arithmetic operators.
 E.g.<BR> E.g.<BR>
 +<code>
  <font color=DARKRED><b><code> expr 2 + 1 </code></b></font> <BR>  <font color=DARKRED><b><code> expr 2 + 1 </code></b></font> <BR>
 +</code>
  
 +<code>
  <font color=DARKRED><b><code> expr 2 '*' '(' 21 + 3 ')' </code></b></font> <BR>  <font color=DARKRED><b><code> expr 2 '*' '(' 21 + 3 ')' </code></b></font> <BR>
 +</code>
 Used with text strings, "expr" can match regular expressions and extract sub expressions.  Similar functionality Used with text strings, "expr" can match regular expressions and extract sub expressions.  Similar functionality
 can be achived with <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sed&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sed</code></b></font></a>. can be achived with <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sed&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sed</code></b></font></a>.
 e.g.<BR> e.g.<BR>
- <font color=DARKRED><b><code> expr SP99302L.Z00 : '[A-Z0-9]]\{4\}\([[0-9]]\{3\}\)L\.*'</code></b></font>+<code> 
 + <font color=DARKRED><b><code> expr SP99302L.Z00 : '[[A-Z0-9]]\\{4\\}\\([[0-9]]\\{3\\}\\)L\\.*'</code></b></font
 +</code>
  
 <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=dc&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>dc</code></b></font></a> <DT><a href="http://www.FreeBSD.org/cgi/man.cgi?query=dc&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>dc</code></b></font></a>
Line 3074: Line 3149:
 </DL> </DL>
  
-<h3>Merging files</h3>+====Merging files====
  
 <DL> <DL>
Line 3095: Line 3170:
  
 <p align=RIGHT class="newpage"><font size=-1>(33)</font></P> <p align=RIGHT class="newpage"><font size=-1>(33)</font></P>
-<font color=DARKBLUE><h1>References, Resources, Man pages etc.</H1></font>+<font color=DARKBLUE>======References, Resources, Man pages etc.</H1></font>
  
 The standard man pages for <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sh</code></b></font></a> and <a href="http://www.FreeBSD.org/cgi/man.cgi?query=ksh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>ksh</code></b></font></a> are quite complete, but not easy to The standard man pages for <a href="http://www.FreeBSD.org/cgi/man.cgi?query=sh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>sh</code></b></font></a> and <a href="http://www.FreeBSD.org/cgi/man.cgi?query=ksh&apropos=0&sektion=1&manpath=Red+Hat+Linux%2Fi386+9&format=html" target=manpage><font color=DARKRED><b><code>ksh</code></b></font></a> are quite complete, but not easy to
 learn from.  The following is a sampling of the many available books on the subject.  The Bolsky and Korn learn from.  The following is a sampling of the many available books on the subject.  The Bolsky and Korn
-book might be viewed as the standard "reference" The Blinn book is Bourne shell, but everything in it should  +book might be viewed as the standard "reference" The Blinn book is Bourne shell, but everything in it should 
-work for either shell.<BR>  +work for either shell.<BR> 
-The links are to publisher's web sites, or Amazon.com. Some links are also given to the example +The links are to publisher's web sites, or Amazon.com. Some links are also given to the example
 scripts provided with the books. scripts provided with the books.
  
 <P> <P>
-<h3>Books</h3>+====Books====
 <UL> <UL>
 <LI><I>The New KornShell Command And Programming Language</I>, by Morris I. Bolsky, David G. Korn (Contributor). <LI><I>The New KornShell Command And Programming Language</I>, by Morris I. Bolsky, David G. Korn (Contributor).
Line 3131: Line 3206:
  
 <LI><I>Linux Shell Scripting with Bash</I> by Ken O. Burtch. <LI><I>Linux Shell Scripting with Bash</I> by Ken O. Burtch.
-<A HREF=http://www.samspublishing.com/title/0672326426> +<A HREF=http://www.samspublishing.com/title/0672326426>
 <SMALL>More info</SMALL></A><BR> <SMALL>More info</SMALL></A><BR>
 <BR> <BR>
Line 3166: Line 3241:
 </SMALL><BR><BR> </SMALL><BR><BR>
  
-<LI><I>Unix Power Tools</I>, by S. Powers, J. Peek, T. O'Reilly, M. Loudikes et al.  +<LI><I>Unix Power Tools</I>, by S. Powers, J. Peek, T. O'Reilly, M. Loudikes et al.
 <A HREF="http://www.oreilly.com/catalog/upt3/"> <A HREF="http://www.oreilly.com/catalog/upt3/">
 <SMALL>More info</SMALL></A> <SMALL>More info</SMALL></A>
 </UL> </UL>
 <P> <P>
-<h3>Online Resources</h3>+====Online Resources====
  
 <UL> <UL>
Line 3184: Line 3259:
 <SMALL>Good resource on advanced use of OSX and Unix shell scripting in general</SMALL> <SMALL>Good resource on advanced use of OSX and Unix shell scripting in general</SMALL>
 </UL> </UL>
-<h3>Unix-like shells and utilities for Microsoft Windows</h3>+====Unix-like shells and utilities for Microsoft Windows====
 <UL> <UL>
 <LI><A HREF="http://www.research.att.com/sw/tools/uwin/" TARGET=external>U/Win</A> (http://www.research.att.com/sw/tools/uwin/)<BR> <LI><A HREF="http://www.research.att.com/sw/tools/uwin/" TARGET=external>U/Win</A> (http://www.research.att.com/sw/tools/uwin/)<BR>
Line 3194: Line 3269:
  
 <SMALL> <SMALL>
-A free Linux-like environment for Windows.  Provides bash, command line utilities and DLLs.  Developed by RedHat.  An +A free Linux-like environment for Windows.  Provides bash, command line utilities and DLLs.  Developed by RedHat.  An
 X server is also available. X server is also available.
 </SMALL> </SMALL>
Line 3206: Line 3281:
 <SMALL> <SMALL>
  
-A POSIX environment for Windows, with ksh, csh, command line tools, libraries and software development tools.  +A POSIX environment for Windows, with ksh, csh, command line tools, libraries and software development tools.
 Developed by Interix and bought by Microsoft.  Free download. Developed by Interix and bought by Microsoft.  Free download.
 </SMALL> </SMALL>
Line 3224: Line 3299:
 </body> </body>
 </html> </html>
 +
advanced_shell_scripting.1544273360.txt.gz · Last modified: 2018/12/08 12:49 by 0.0.0.0

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki