| Next revision | Previous revision |
| advanced_shell_scripting [2018/12/06 21:05] – created 91.177.234.129 | advanced_shell_scripting [2019/01/30 11:32] (current) – external edit 127.0.0.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> |
| </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> |
| |
| <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> |
| (<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, |
| <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. |
| <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) |
| Richard Brittain, Dartmouth College Computing Services. | Richard Brittain, Dartmouth College Computing Services. |
| <BR> | <BR> |
| © 2003,2004,2010 Dartmouth College. | © 2003,2004,2010 Dartmouth College. |
| |
| <BR> | <BR> |
| |
| <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> |
| |
| <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> |
| <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. |
| <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> |
| <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> |
| <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> |
| <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> |
| |
| <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> |
| <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> |
| <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> |
| |
| <DD>The "Korn" shell, written by David Korn of AT&T Bell Labs (now AT&T Research). | <DD>The "Korn" shell, written by David Korn of AT&T Bell Labs (now AT&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&T licensing. | It was slow to gain acceptance because earlier versions were encumbered by AT&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&T SVR4 Unix, and may still be installed | There are two major versions. ksh88 was the version incorporated into AT&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> |
| <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 |
| |
| <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> |
| <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 |
| 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. |
| |
| <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. |
| |
| |
| <LI>Conditional execution using <font color=DARKRED><b><code>&&</code></b></font> and <font color=DARKRED><b><code>||</code></b></font> | <LI>Conditional execution using <font color=DARKRED><b><code>&&</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> |
| |
| <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 |
| <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> |
| <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> |
| 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 |
| |
| <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> |
| |
| <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 |
| |
| <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 |
| <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. |
| |
| <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 |
| |
| <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> |
| 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. |
| |
| |
| <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> |
| |
| <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> |
| </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. |
| 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> |
| |
| <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 |
| <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. |
| |
| <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> |
| </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. |
| <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. |
| |
| 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> |
| |
| </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: |
| |
| <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> |
| 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> |
| <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. |
| <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> |
| <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) |
| <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) |
| |
| <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. |
| <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: |
| <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. |
| <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> |
| <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> |
| |
| </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. |
| <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> |
| |
| <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>" |
| |
| <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 |
| |
| <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> |
| |
| </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>$(<file)</code></b></font> | <DT><font color=DARKRED><b><code>$(<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. |
| <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 < <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 < <font color=BLACK>$file</font></font>) lines |
| |
| <font color=GRAY> 7:</font> | <font color=GRAY> 7:</font> |
| <font color=GRAY> 8:</font> hostname -s > myhostname | <font color=GRAY> 8:</font> hostname -s > myhostname |
| <font color=GRAY> 9:</font> <font color=DARKBLUE>echo </font>This system has host name $(<font color=PURPLE><myhostname</font>) | <font color=GRAY> 9:</font> <font color=DARKBLUE>echo </font>This system has host name $(<font color=PURPLE><myhostname</font>) |
| |
| <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 |
| the command is run. | the command is run. |
| |
| <h2>Output redirection</h2> | =====Output redirection===== |
| <DL> | <DL> |
| <DT><font color=DARKRED><b><code>> <I>filename</I></code></b></font> | <DT><font color=DARKRED><b><code>> <I>filename</I></code></b></font> |
| </DL> | </DL> |
| |
| <h2>Input redirection</h2> | =====Input redirection===== |
| <DL> | <DL> |
| <DT><font color=DARKRED><b><code>< <I>filename</I></code></b></font> | <DT><font color=DARKRED><b><code>< <I>filename</I></code></b></font> |
| </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 |
| 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. |
| |
| <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> |
| 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>\n </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> |
| </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> |
| <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> |
| <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> |
| |
| |
| <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 |
| 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> |
| <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> |
| </DL> | </DL> |
| |
| <h3>Character string tests</h3> | ====Character string tests==== |
| |
| <DL> | <DL> |
| |
| <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> |
| <DT><font color=DARKRED><b><code>$variable < <I>text</I></code></b></font> | <DT><font color=DARKRED><b><code>$variable < <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>></code></b></font> = comes after | <code> |
| | Similarly, <font color=DARKRED><b><code>></code></b></font> = comes after |
| | </code> |
| </DL> | </DL> |
| |
| |
| <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> |
| <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 |
| |
| |
| <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> |
| <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> |
| |
| <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> |
| |
| <PRE> | <PRE> |
| mkdir tempdir && cp workfile tempdir || \ | mkdir tempdir && cp workfile tempdir || \\ |
| | <code> |
| echo "Failed to create tempdir" | echo "Failed to create tempdir" |
| | </code> |
| </PRE> | </PRE> |
| </small></blockquote> | </small></blockquote> |
| <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> |
| </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> |
| 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> |
| 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> |
| <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> |
| <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> |
| |
| <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> |
| <I>Example:</I> | <I>Example:</I> |
| <PRE> | <PRE> |
| | <code> |
| case $filename in | case $filename in |
| *.dat) | *.dat) |
| ;; | ;; |
| 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> |
| <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> |
| |
| <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> |
| |
| |
| <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 |
| <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 |
| <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 |
| |
| <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 |
| <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> |
| |
| <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> |
| <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) |
| |
| <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> |
| |
| |
| <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> |
| </DL> | </DL> |
| |
| <h2>Numeric variables</h2> | =====Numeric variables===== |
| |
| <DL> | <DL> |
| 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> |
| (*,/,+,-,|,&,<<,>>. Use parentheses for changing precedence). | (*,/,+,-,|,&,<<,>>. Use parentheses for changing precedence). |
| | </code> |
| </DL> | </DL> |
| |
| <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> |
| |
| |
| <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, |
| 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> |
| 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. |
| 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 |
| 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 |
| <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> |
| <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> { |
| |
| <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 |
| 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. |
| print -R $* | print -R $* |
| fi | fi |
| | </code> |
| } | } |
| |
| </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 |
| |
| <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> > outfile < 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> > outfile < 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>outfile</code></b></font> | <DT><font color=DARKRED><b><code>exec n>outfile</code></b></font> |
| | </code> |
| |
| | <code> |
| <DD>The form n<, n> opens file descriptor n instead of the default stdin/stdout. | <DD>The form n<, n> 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 |
| <DL> | <DL> |
| |
| | <code> |
| <DT><font color=DARKRED><b><code>>&n</code></b></font> | <DT><font color=DARKRED><b><code>>&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 |
| <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>&1</code></b></font> | <DT><font color=DARKRED><b><code>n>&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" >&2 | echo "Error: program failed" >&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 |
| 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 |&) | <DD>write to the pipe to a coprocess (opened by |&) |
| | </code> |
| </DL> | </DL> |
| |
| 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 |&) | <DD>read from the pipe to a coprocess (opened by |&) |
| | </code> |
| </DL> | </DL> |
| <P> | <P> |
| |
| <h3>Closing file handles</h3> | ====Closing file handles==== |
| <DL> | <DL> |
| | <code> |
| <DT><font color=DARKRED><b><code><&-</code></b></font> | <DT><font color=DARKRED><b><code><&-</code></b></font> |
| <DD>standard input is explicitly closed | <DD>standard input is explicitly closed |
| <DT><font color=DARKRED><b><code>>&-</code></b></font> | <DT><font color=DARKRED><b><code>>&-</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>>filename 2>&1</code></b></font>". (Many books with example scripts get this wrong) | "<font color=DARKRED><b><code>>filename 2>&1</code></b></font>". (Many books with example scripts get this wrong) |
| |
| <h3>"Here" documents</h3> | ===="Here" documents==== |
| |
| <DL> | <DL> |
| |
| <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 <<EOF | <font color=GRAY> 4:</font> cat <<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 |
| <font color=GRAY> 13:</font> cat <<"EndOfInput" | <font color=GRAY> 13:</font> cat <<"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. |
| |
| |
| <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 << EOP | <font color=GRAY> 9:</font> cat << EOP |
| |
| <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. |
| <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> |
| <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>&1 | <font color=GRAY> 10:</font> <font color=DARKBLUE>exec </font>3>&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> |
| <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>&1 1>&3 3>&- | sed 's/stderr/STDERR/' 1>&2 | <font color=GRAY> 15:</font> ./ex13.sh 2>&1 1>&3 3>&- | sed 's/stderr/STDERR/' 1>&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> |
| |
| </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> |
| <font color=DARKRED><b><code> ex13stat=`((./ex13.sh; echo $? >&4) | grep 'foo' 1>&3) 4>&1` </code></b></font><BR> | <font color=DARKRED><b><code> ex13stat=`((./ex13.sh; echo $? >&4) | grep 'foo' 1>&3) 4>&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 |
| <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>&1 | <font color=GRAY> 11:</font> <font color=DARKBLUE>exec </font>3>&1 |
| <font color=GRAY> 21:</font> <font color=BLACK>ex13stat=</font>`<font color=PURPLE>((./ex13.sh; <font color=DARKBLUE>echo </font>$? >&4) | grep 'foo' 1>&3) 4>&1</font>` | <font color=GRAY> 21:</font> <font color=BLACK>ex13stat=</font>`<font color=PURPLE>((./ex13.sh; <font color=DARKBLUE>echo </font>$? >&4) | grep 'foo' 1>&3) 4>&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> |
| <font color=GRAY> 29:</font> <font color=DARKBLUE>exec </font>3>&1 | <font color=GRAY> 29:</font> <font color=DARKBLUE>exec </font>3>&1 |
| |
| <font color=GRAY> 30:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 3>&- 4>&- ; <font color=DARKBLUE>echo </font>$? >&4) | \ | <font color=GRAY> 30:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 3>&- 4>&- ; <font color=DARKBLUE>echo </font>$? >&4) | \\ |
| <font color=GRAY> 31:</font> grep 'foo' 1>&3 3>&- 4>&- ) 4>&1` | <font color=GRAY> 31:</font> grep 'foo' 1>&3 3>&- 4>&- ) 4>&1` |
| |
| <P> | <P> |
| <font color=DARKRED><b><code>exec 3>&1 </code></b></font><BR> | <font color=DARKRED><b><code>exec 3>&1 </code></b></font><BR> |
| <font color=DARKRED><b><code>ex13stat=`((./ex13.sh 2>&1 1>&3 3>&- 4>&- ; echo $? >&4) | \ </code></b></font><BR> | <font color=DARKRED><b><code>ex13stat=`((./ex13.sh 2>&1 1>&3 3>&- 4>&- ; echo $? >&4) | \\ </code></b></font><BR> |
| |
| <font color=DARKRED><b><code> sed s/err/ERR/ 1>&2 3>&- 4>&- ) 4>&1` </code></b></font> | <font color=DARKRED><b><code> sed s/err/ERR/ 1>&2 3>&- 4>&- ) 4>&1` </code></b></font> |
| <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>&1 | <font color=GRAY> 12:</font> <font color=DARKBLUE>exec </font>3>&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>&1`</i></font> | <font color=GRAY> 16:</font> <font color=DARKGREEN><i># ex13stat=`( ) 4>&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>$? >&4)</i></font> | <font color=GRAY> 20:</font> <font color=DARKGREEN><i># (./ex13.sh; <font color=DARKBLUE>echo </font>$? >&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>&1 | <font color=GRAY> 27:</font> <font color=DARKBLUE>exec </font>3>&1 |
| |
| <font color=GRAY> 28:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 2>&1 1>&3 3>&- 4>&- ; <font color=DARKBLUE>echo </font>$? >&4) | \ | <font color=GRAY> 28:</font> <font color=BLACK>ex13stat=</font>`((./ex13.sh 2>&1 1>&3 3>&- 4>&- ; <font color=DARKBLUE>echo </font>$? >&4) | \\ |
| <font color=GRAY> 29:</font> sed s/err/ERR/ 1>&2 3>&- 4>&- ) 4>&1` | <font color=GRAY> 29:</font> sed s/err/ERR/ 1>&2 3>&- 4>&- ) 4>&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> |
| <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), |
| </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 |
| <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 >/dev/tty |& | <font color=GRAY> 15:</font> tee <font color=BLACK>$0</font>.out >/dev/tty |& |
| <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>&p | <font color=GRAY> 18:</font> <font color=DARKBLUE>exec </font>1>&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> |
| <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 |& | <font color=GRAY> 6:</font> dndlookup -fname -u |& |
| <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> |
| |
| <font color=GRAY> 11:</font> <font color=DARKBLUE>exec </font>5<&p | <font color=GRAY> 11:</font> <font color=DARKBLUE>exec </font>5<&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> |
| <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> *) |
| <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>< namefile | <font color=GRAY> 37:</font> <font color=DARKBLUE>done </font>< 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> |
| |
| <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. |
| <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> { |
| |
| <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> { |
| <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> |
| <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> |
| |
| <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> |
| |
| <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> |
| |
| <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> |
| |
| <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> |
| |
| <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> |
| <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> |
| |
| |
| <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 |
| 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>. |
| |
| <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> { |
| |
| <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> { |
| |
| <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> |
| |
| <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. |
| |
| <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> |
| 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, |
| <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> |
| 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> |
| <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> |
| <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/\\\'/\\\\\'/g \ | sed -es/\\\\\\\\/\\\\\\\\\\\\\\\\/g \\ |
| -es/\\\"/\\\\\"/g \ | -es/\\\\\\'/\\\\\\\\\\'/g \\ |
| -es/\\\;/\\\\\;/g \ | -es/\\\\\\"/\\\\\\\\\\"/g \\ |
| -es/\\\?/\\\\\?/g \ | -es/\\\\\\;/\\\\\\\\\\;/g \\ |
| -es/\\\*/\\\\\*/g \ | -es/\\\\\\?/\\\\\\\\\\?/g \\ |
| -es/\\\ /\\\\\ /g | -es/\\\\\\*/\\\\\\\\\\*/g \\ |
| | -es/\\\\\\ /\\\\\\\\\\ /g |
| | </code> |
| } | } |
| </PRE> | </PRE> |
| |
| <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. |
| <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 |
| </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> |
| <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, |
| |
| <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. |
| 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> |
| --> | --> |
| <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> |
| |
| <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 |
| 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> |
| </DL> | </DL> |
| |
| <h3>Displaying text, files or parts of files</h3> | ====Displaying text, files or parts of files==== |
| |
| <DL> | <DL> |
| 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> |
| </DL> | </DL> |
| |
| <h3>Compression and archiving</h3> | ====Compression and archiving==== |
| |
| <DL> | <DL> |
| </DL> | </DL> |
| |
| <h3>Sorting and searching for patterns</h3> | ====Sorting and searching for patterns==== |
| |
| <DL> | <DL> |
| </DL> | </DL> |
| |
| <h3>System information (users, processes, time)</h3> | ====System information (users, processes, time)==== |
| |
| <DL> | <DL> |
| <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. |
| |
| </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. |
| </DL> | </DL> |
| |
| <h3>Stream Editing</h3> | ====Stream Editing==== |
| |
| <DL> | <DL> |
| </DL> | </DL> |
| |
| <h3>Finding and comparing files</h3> | ====Finding and comparing files==== |
| |
| <DL> | <DL> |
| </DL> | </DL> |
| |
| <h3>Arithmetic and String Manipulation</h3> | ====Arithmetic and String Manipulation==== |
| |
| <DL> | <DL> |
| 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> |
| </DL> | </DL> |
| |
| <h3>Merging files</h3> | ====Merging files==== |
| |
| <DL> | <DL> |
| |
| <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). |
| |
| <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> |
| </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> |
| <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> |
| |
| <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> |
| <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> |
| </body> | </body> |
| </html> | </html> |
| | |