<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
<!--
Uncomment line below to generate index.
-->
<!--
<!ENTITY indice SYSTEM "indice.sgml">
-->
<!ENTITY ex1 SYSTEM "ex1.sh">
<!ENTITY ex2 SYSTEM "ex2.sh">
<!ENTITY ex3 SYSTEM "ex3.sh">
<!ENTITY ex4 SYSTEM "ex4.sh">
<!ENTITY ex5 SYSTEM "ex5.sh">
<!ENTITY ex6 SYSTEM "ex6.sh">
<!ENTITY ex7 SYSTEM "ex7.sh">
<!ENTITY ex8 SYSTEM "ex8.sh">
<!ENTITY ex9 SYSTEM "ex9.sh">
<!ENTITY ex10 SYSTEM "ex10.sh">
<!ENTITY ex11 SYSTEM "ex11.sh">
<!ENTITY ex12 SYSTEM "ex12.sh">
<!ENTITY ex13 SYSTEM "ex13.sh">
<!ENTITY ex14 SYSTEM "ex14.sh">
<!ENTITY ex15 SYSTEM "ex15.sh">
<!ENTITY ex16 SYSTEM "ex16.sh">
<!ENTITY ex17 SYSTEM "ex17.sh">
<!ENTITY ex18 SYSTEM "ex18.sh">
<!ENTITY ex19 SYSTEM "ex19.sh">
<!ENTITY ex20 SYSTEM "ex20.sh">
<!ENTITY ex21 SYSTEM "ex21.sh">
<!ENTITY ex22 SYSTEM "ex22.sh">
<!ENTITY ex22a SYSTEM "ex22a.sh">
<!ENTITY ex23 SYSTEM "ex23.sh">
<!ENTITY ex24 SYSTEM "ex24.sh">
<!ENTITY ex25 SYSTEM "ex25.sh">
<!ENTITY ex26 SYSTEM "ex26.sh">
<!ENTITY ex26a SYSTEM "ex26a.sh">
<!ENTITY ex27 SYSTEM "ex27.sh">
<!ENTITY ex28 SYSTEM "ex28.sh">
<!ENTITY ex29 SYSTEM "ex29.sh">
<!ENTITY ex30 SYSTEM "ex30.sh">
<!ENTITY ex30a SYSTEM "ex30a.sh">
<!ENTITY ex31 SYSTEM "ex31.sh">
<!ENTITY ex32 SYSTEM "ex32.sh">
<!ENTITY ex33 SYSTEM "ex33.sh">
<!ENTITY ex33a SYSTEM "ex33a.sh">
<!ENTITY ex34 SYSTEM "ex34.sh">
<!ENTITY ex35 SYSTEM "ex35.sh">
<!ENTITY ex36 SYSTEM "ex36.sh">
<!ENTITY ex37 SYSTEM "ex37.sh">
<!ENTITY ex38 SYSTEM "ex38.sh">
<!ENTITY ex38bis SYSTEM "data-file">
<!ENTITY ex39 SYSTEM "ex39.sh">
<!ENTITY ex40 SYSTEM "ex40.sh">
<!ENTITY ex41 SYSTEM "ex41.sh">
<!ENTITY ex42 SYSTEM "ex42.sh">
<!ENTITY ex43 SYSTEM "ex43.sh">
<!ENTITY ex44 SYSTEM "ex44.sh">
<!ENTITY ex45 SYSTEM "ex45.sh">
<!ENTITY ex45a SYSTEM "ex45a.sh">
<!ENTITY ex46 SYSTEM "ex46.sh">
<!ENTITY ex47 SYSTEM "ex47.sh">
<!ENTITY ex48 SYSTEM "ex48.sh">
<!ENTITY ex49 SYSTEM "ex49.sh">
<!ENTITY ex50 SYSTEM "ex50.sh">
<!ENTITY ex51 SYSTEM "ex51.sh">
<!ENTITY ex52 SYSTEM "ex52.sh">
<!ENTITY ex53 SYSTEM "ex53.sh">
<!ENTITY ex54 SYSTEM "ex54.sh">
<!ENTITY ex55 SYSTEM "ex55.sh">
<!ENTITY ex56 SYSTEM "ex56.sh">
<!ENTITY ex57 SYSTEM "ex57.sh">
<!ENTITY ex58 SYSTEM "ex58.sh">
<!ENTITY ex59 SYSTEM "ex59.sh">
<!ENTITY ex60 SYSTEM "ex60.sh">
<!ENTITY ex61 SYSTEM "ex61.sh">
<!ENTITY ex62 SYSTEM "ex62.sh">
<!ENTITY ex63 SYSTEM "ex63.sh">
<!ENTITY ex64 SYSTEM "ex64.sh">
<!ENTITY ex65 SYSTEM "ex65.sh">
<!ENTITY ex66 SYSTEM "ex66.sh">
<!ENTITY ex67 SYSTEM "ex67.sh">
<!ENTITY ex68 SYSTEM "ex68.sh">
<!ENTITY ex69 SYSTEM "ex69.sh">
<!ENTITY ex70 SYSTEM "ex70.sh">
<!ENTITY ex71 SYSTEM "ex71.sh">
<!ENTITY ex71a SYSTEM "ex71a.sh">
<!ENTITY ex71b SYSTEM "ex71b.sh">
<!ENTITY ex71c SYSTEM "ex71c.sh">
<!ENTITY ex72 SYSTEM "ex72.sh">
<!ENTITY ex73 SYSTEM "ex73.sh">
<!ENTITY ex74 SYSTEM "ex74.sh">
<!ENTITY ex75 SYSTEM "ex75.sh">
<!ENTITY ex76 SYSTEM "ex76.sh">
<!ENTITY ex77 SYSTEM "ex77.sh">
<!ENTITY ex78 SYSTEM "ex78.sh">
<!ENTITY ex79 SYSTEM "ex79.sh">
<!ENTITY andor SYSTEM "and-or.sh">
<!ENTITY lnum SYSTEM "line-number.sh">
<!ENTITY manview SYSTEM "manview.sh">
<!ENTITY rfe SYSTEM "rfe.sh">
<!ENTITY behead SYSTEM "behead.sh">
<!ENTITY ftpget SYSTEM "ftpget.sh">
<!ENTITY encryptedpw SYSTEM "encryptedpw.sh">
<!ENTITY rpmcheck SYSTEM "rpm-check.sh">
<!ENTITY subshell SYSTEM "subshell.sh">
<!ENTITY lowercase SYSTEM "lowercase.sh">
<!ENTITY online SYSTEM "online.sh">
<!ENTITY reply SYSTEM "reply.sh">
<!ENTITY seconds SYSTEM "seconds.sh">
<!ENTITY numbers SYSTEM "numbers.sh">
<!ENTITY indref SYSTEM "ind-ref.sh">
<!ENTITY bubble SYSTEM "bubble.sh">
<!ENTITY paramsub SYSTEM "param-sub.sh">
<!ENTITY restricted SYSTEM "restricted.sh">
<!ENTITY pw SYSTEM "pw.sh">
<!ENTITY rn SYSTEM "rn.sh">
<!ENTITY coltotaler SYSTEM "col-totaler.sh">
<!ENTITY coltotaler2 SYSTEM "col-totaler2.sh">
<!ENTITY coltotaler3 SYSTEM "col-totaler3.sh">
<!ENTITY tmdin SYSTEM "timed-input.sh">
<!ENTITY fifo SYSTEM "fifo.sh">
<!ENTITY tree SYSTEM "tree.sh">
<!ENTITY secretpw SYSTEM "secret-pw.sh">
<!ENTITY stripc SYSTEM "strip-comments.sh">
<!ENTITY al SYSTEM "alias.sh">
<!ENTITY unal SYSTEM "unalias.sh">
<!ENTITY redir1 SYSTEM "redir1.sh">
<!ENTITY redir2 SYSTEM "redir2.sh">
<!ENTITY redir2a SYSTEM "redir2a.sh">
<!ENTITY redir3 SYSTEM "redir3.sh">
<!ENTITY redir4 SYSTEM "redir4.sh">
<!ENTITY redir4a SYSTEM "redir4a.sh">
<!ENTITY redir5 SYSTEM "redir5.sh">
<!ENTITY wipedir SYSTEM "wipedir.sh">
<!ENTITY grp SYSTEM "grp.sh">
<!ENTITY killprocess SYSTEM "kill-process.sh">
<!ENTITY strtest SYSTEM "str-test.sh">
<!ENTITY colm SYSTEM "colm.sh">
<!ENTITY lookup SYSTEM "lookup.sh">
<!ENTITY arglist SYSTEM "arglist.sh">
<!ENTITY rot13 SYSTEM "rot13.sh">
<!ENTITY rot14 SYSTEM "rot14.sh">
<!ENTITY filecomp SYSTEM "file-comparison.sh">
<!ENTITY adddrv SYSTEM "add-drive.sh">
<!ENTITY whloopc SYSTEM "wh-loopc.sh">
<!ENTITY forloopc SYSTEM "for-loopc.sh">
<!ENTITY forloopcmd SYSTEM "for-loopcmd.sh">
<!ENTITY cvars SYSTEM "c-vars.sh">
<!ENTITY bingrep SYSTEM "bin-grep.sh">
<!ENTITY mailformat SYSTEM "mail-format.sh">
<!ENTITY symlinks SYSTEM "symlinks.sh">
<!ENTITY symlinks2 SYSTEM "symlinks2.sh">
<!ENTITY string SYSTEM "string.sh">
<!ENTITY nestedloop SYSTEM "nested-loop.sh">
<!ENTITY casecmd SYSTEM "case-cmd.sh">
<!ENTITY uns SYSTEM "unset.sh">
<!ENTITY base SYSTEM "base.sh">
<!ENTITY allprofs SYSTEM "allprofs.sh">
<!ENTITY pidid SYSTEM "pid-identifier.sh">
<!ENTITY constat SYSTEM "connect-stat.sh">
<!ENTITY subpit SYSTEM "subshell-pitfalls.sh">
<!ENTITY readredir SYSTEM "read-redir.sh">
<!ENTITY andlist2 SYSTEM "and-list2.sh">
<!ENTITY qfunction SYSTEM "q-function.sh">
<!ENTITY viewdata SYSTEM "viewdata.sh">
<!ENTITY VIEWDAT SYSTEM "VIEWDATA.BAT">
<!ENTITY what SYSTEM "what.sh">
<!ENTITY max SYSTEM "max.sh">
<!ENTITY max2 SYSTEM "max2.sh">
<!ENTITY findstring SYSTEM "findstring.sh">
<!ENTITY listglob SYSTEM "list-glob.sh">
<!ENTITY realname SYSTEM "realname.sh">
<!ENTITY escaped SYSTEM "escaped.sh">
<!ENTITY fileinfo SYSTEM "file-info.sh">
<!ENTITY weirdvars SYSTEM "weirdvars.sh">
<!ENTITY breaklevels SYSTEM "break-levels.sh">
<!ENTITY copycd SYSTEM "copy-cd.sh">
<!ENTITY arithops SYSTEM "arith-ops.sh">
<!ENTITY continuelevels SYSTEM "continue-nlevel.sh">
<!ENTITY timeout SYSTEM "timeout.sh">
<!ENTITY randomtest SYSTEM "random-test.sh">
<!ENTITY seedingrandom SYSTEM "seeding-random.sh">
<!ENTITY pattmatching SYSTEM "patt-matching.sh">
<!ENTITY isalpha SYSTEM "isalpha.sh">
<!ENTITY rnd SYSTEM "rnd.sh">
<!ENTITY du SYSTEM "du.sh">
<!ENTITY refparams SYSTEM "ref-params.sh">
<!ENTITY primes SYSTEM "primes.sh">
<!ENTITY vartrace SYSTEM "vartrace.sh">
<!ENTITY amiroot SYSTEM "am-i-root.sh">
<!ENTITY twodim SYSTEM "twodim.sh">
<!ENTITY arithtests SYSTEM "arith-tests.sh">
<!ENTITY incompat SYSTEM "incompat.sh">
<!ENTITY ifsh SYSTEM "ifs.sh">
<!ENTITY ifsempty SYSTEM "ifs-empty.sh">
<!ENTITY logevents SYSTEM "logevents.sh">
<!ENTITY keypress SYSTEM "keypress.sh">
<!ENTITY ddkeypress SYSTEM "dd-keypress.sh">
<!ENTITY objoriented SYSTEM "obj-oriented.sh">
<!ENTITY emptyarray SYSTEM "empty-array.sh">
<!ENTITY length SYSTEM "length.sh">
<!ENTITY monthlypmt SYSTEM "monthlypmt.sh">
<!ENTITY derpm SYSTEM "de-rpm.sh">
<!ENTITY blotout SYSTEM "blot-out.sh">
<!ENTITY readr SYSTEM "read-r.sh">
<!ENTITY cryptoquote SYSTEM "crypto-quote.sh">
<!ENTITY erase SYSTEM "erase.sh">
<!ENTITY returntest SYSTEM "return-test.sh">
<!ENTITY daysbetween SYSTEM "days-between.sh">
<!ENTITY varmatch SYSTEM "var-match.sh">
<!ENTITY recurse SYSTEM "recurse.sh">
<!ENTITY assert SYSTEM "assert.sh">
<!ENTITY intorstring SYSTEM "int-or-string.sh">
<!ENTITY ramdisk SYSTEM "ramdisk.sh">
<!ENTITY m4 SYSTEM "m4.sh">
<!ENTITY idelete SYSTEM "idelete.sh">
<!ENTITY matchstring SYSTEM "match-string.sh">
<!ENTITY bashandperl SYSTEM "bashandperl.sh">
<!ENTITY cvt SYSTEM "cvt.sh">
<!ENTITY wf SYSTEM "wf.sh">
<!ENTITY hypot SYSTEM "hypotenuse.sh">
<!ENTITY random2 SYSTEM "random2.sh">
<!ENTITY altbc SYSTEM "alt-bc.sh">
<!ENTITY substringex SYSTEM "substring-extraction.sh">
<!ENTITY stupscr SYSTEM "stupid-script-tricks.sh">
<!ENTITY resistor SYSTEM "resistor-inventory.sh">
<!ENTITY stackex SYSTEM "stack.sh">
<!ENTITY gcd SYSTEM "gcd.sh">
<!ENTITY selfmailer SYSTEM "self-mailer.sh">
<!ENTITY collatz SYSTEM "collatz.sh">
<!ENTITY wstrings SYSTEM "wstrings.sh">
<!ENTITY multiplication SYSTEM "multiplication.sh">
<!ENTITY sumproduct SYSTEM "sum-product.sh">
<!ENTITY userlist SYSTEM "userlist.sh">
<!ENTITY bgloop SYSTEM "background-loop.sh">
<!ENTITY tout SYSTEM "t-out.sh">
<!ENTITY csubloop SYSTEM "csubloop.sh">
<!ENTITY arrfunc SYSTEM "array-function.sh">
<!ENTITY lifeslow SYSTEM "life.sh">
<!ENTITY commentblock SYSTEM "commentblock.sh">
<!ENTITY selfdocument SYSTEM "self-document.sh">
<!ENTITY hf SYSTEM "here-function.sh">
<!ENTITY fileintegrity SYSTEM "file-integrity.sh">
<!ENTITY readnovar SYSTEM "read-novar.sh">
<!ENTITY setpos SYSTEM "set-pos.sh">
<!ENTITY badread SYSTEM "badread.sh">
<!ENTITY selfexec SYSTEM "self-exec.sh">
<!ENTITY selfdestruct SYSTEM "self-destruct.sh">
<!ENTITY reassignstdout SYSTEM "reassign-stdout.sh">
<!ENTITY upperconv SYSTEM "upperconv.sh">
<!ENTITY pbook SYSTEM "pb.sh">
<!ENTITY makedict SYSTEM "makedict.sh">
<!ENTITY missingkeyword SYSTEM "missing-keyword.sh">
<!ENTITY blankrename SYSTEM "blank-rename.sh">
<!ENTITY scriptdetector SYSTEM "script-detector.sh">
<!ENTITY hexconvert SYSTEM "hexconvert.sh">
<!ENTITY factr SYSTEM "factr.sh">
<!ENTITY cannon SYSTEM "cannon.sh">
<!ENTITY agram SYSTEM "agram.sh">
<!ENTITY poem SYSTEM "poem.sh">
<!ENTITY soundex SYSTEM "soundex.sh">
<!ENTITY tempfilename SYSTEM "tempfile-name.sh">
<!ENTITY unitconversion SYSTEM "unit-conversion.sh">
<!ENTITY usagemessage SYSTEM "usage-message.sh">
<!ENTITY colorecho SYSTEM "color-echo.sh">
<!ENTITY selfsource SYSTEM "self-source.sh">
<!ENTITY arrowdetect SYSTEM "arrow-detect.sh">
<!ENTITY paragraphspace SYSTEM "paragraph-space.sh">
<!ENTITY brokenlink SYSTEM "broken-link.sh">
<!ENTITY continuenex SYSTEM "continue-n.example">
<!ENTITY pickcard SYSTEM "pick-card.sh">
<!ENTITY copyarray SYSTEM "CopyArray.sh">
<!ENTITY directoryinfo SYSTEM "directory-info.sh">
<!ENTITY embarr SYSTEM "embedded-arrays.sh">
<!ENTITY generatescript SYSTEM "generate-script.sh">
<!ENTITY scriptarray SYSTEM "script-array.sh">
<!ENTITY usrmnt SYSTEM "usrmnt.sh">
<!ENTITY dialog SYSTEM "dialog.sh">
<!ENTITY evalex SYSTEM "eval.example">
<!ENTITY namesdata SYSTEM "names.data">
<!ENTITY gen0data SYSTEM "gen0">
<!ENTITY bashrc SYSTEM "bashrc">
]>

<book>
  <bookinfo>
    <title>Advanced Bash-Scripting Guide</title>
    <subtitle>An in-depth exploration of the art of shell scripting</subtitle>


    <author>
      <firstname>Mendel</firstname>
      <surname>Cooper</surname>
      <affiliation>
	<orgname></orgname>
	<address><email>thegrendel@theriver.com</email></address>
      </affiliation>
    </author>

    <releaseinfo>2.1.3</releaseinfo>
    <pubdate>30 September 2003</pubdate>


    <revhistory>

      <revision>
        <revnumber>0.1</revnumber>
        <date>14 June 2000</date>
        <authorinitials>mc</authorinitials>
        <revremark>Initial release.</revremark>
      </revision>

      <revision>
        <revnumber>0.2</revnumber>
        <date>30 October 2000</date>
        <authorinitials>mc</authorinitials>
        <revremark>Bugs fixed, plus much additional material and more example
	scripts.</revremark>
      </revision>

      <revision>
        <revnumber>0.3</revnumber>
        <date>12 February 2001</date>
        <authorinitials>mc</authorinitials>
        <revremark>Another major update.</revremark>
      </revision>

      <revision>
        <revnumber>0.4</revnumber>
        <date>08 July 2001</date>
        <authorinitials>mc</authorinitials>
        <revremark>More bugfixes, much more material, more
	scripts - a complete revision and expansion of the book.</revremark>
      </revision>

      <revision>
        <revnumber>0.5</revnumber>
        <date>03 September 2001</date>
        <authorinitials>mc</authorinitials>
        <revremark>Major update. Bugfixes, material added, chapters and
	sections reorganized.</revremark>
      </revision>

      <revision>
        <revnumber>1.0</revnumber>
        <date>14 October 2001</date>
        <authorinitials>mc</authorinitials>
        <revremark>Bugfixes, reorganization, material added.
	  Stable release.</revremark>
      </revision>

      <revision>
        <revnumber>1.1</revnumber>
        <date>06 January 2002</date>
        <authorinitials>mc</authorinitials>
        <revremark>Bugfixes, material and scripts added.</revremark>
      </revision>

      <revision>
        <revnumber>1.2</revnumber>
        <date>31 March 2002</date>
        <authorinitials>mc</authorinitials>
        <revremark>Bugfixes, material and scripts added.</revremark>
      </revision>

      <revision>
        <revnumber>1.3</revnumber>
        <date>02 June 2002</date>
        <authorinitials>mc</authorinitials>
        <revremark>'TANGERINE' release: A few bugfixes, much more material
          and scripts added.</revremark>
      </revision>

      <revision>
        <revnumber>1.4</revnumber>
        <date>16 June 2002</date>
        <authorinitials>mc</authorinitials>
        <revremark>'MANGO' release: Quite a number of typos fixed, more material
          and scripts added.</revremark>
      </revision>

      <revision>
        <revnumber>1.5</revnumber>
        <date>13 July 2002</date>
        <authorinitials>mc</authorinitials>
	<revremark>'PAPAYA' release: A few bugfixes, much more material
	  and scripts added.</revremark>
      </revision>

      <revision>
        <revnumber>1.6</revnumber>
        <date>29 September 2002</date>
        <authorinitials>mc</authorinitials>
	<revremark>'POMEGRANATE' release: some bugfixes, more material, one
	  more script added.</revremark>
      </revision>

      <revision>
        <revnumber>1.7</revnumber>
        <date>05 January 2003</date>
        <authorinitials>mc</authorinitials>
	<revremark>'COCONUT' release: a couple of bugfixes, more material, one
	  more script.</revremark>
      </revision>

      <revision>
        <revnumber>1.8</revnumber>
        <date>10 May 2003</date>
        <authorinitials>mc</authorinitials>
	<revremark>'BREADFRUIT' release: a number of bugfixes, more scripts
	  and material.</revremark>
      </revision>

      <revision>
        <revnumber>1.9</revnumber>
        <date>21 June 2003</date>
        <authorinitials>mc</authorinitials>
	<revremark>'PERSIMMON' release: bugfixes and more material.</revremark>
      </revision>

      <revision>
        <revnumber>2.0</revnumber>
        <date>24 August 2003</date>
        <authorinitials>mc</authorinitials>
	<revremark>'GOOSEBERRY' release: Major update.</revremark>
      </revision>

      <revision>
        <revnumber>2.1</revnumber>
        <date>14 September 2003</date>
        <authorinitials>mc</authorinitials>
	<revremark>'HUCKLEBERRY' release: bugfixes and more material.</revremark>
      </revision>

      <revision>
        <revnumber>2.1.3</revnumber>
        <date>30 September 2003</date>
        <authorinitials>mc</authorinitials>
	<revremark>Intermediate update, leading up to 'CRANBERRY' release.</revremark>
      </revision>

    </revhistory>


    <abstract>

      <para>This tutorial assumes no previous knowledge of
	scripting or programming, but progresses rapidly toward an
	intermediate/advanced level of instruction <emphasis>. . . all
	the while sneaking in little snippets of <trademark
	class=registered>UNIX</trademark> wisdom and lore</emphasis>. It
	serves as a textbook, a manual for self-study, and a reference and
	source of knowledge on shell scripting techniques.  The exercises
	and heavily-commented examples invite active reader participation,
	under the premise that <userinput>the only way to really learn
	scripting is to write scripts</userinput>.</para>

      <para>This book is suitable for classroom use as a general
        introduction to programming concepts.</para>

      <para>The latest update of this document, as an archived, <link
	linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
	including both the SGML source and
	rendered HTML, may be downloaded from <ulink
	url="http://personal.riverusers.com/~thegrendel/abs-guide-2.1.tar.bz2">
	the author's home site</ulink>.  See the <ulink
	url="http://personal.riverusers.com/~thegrendel/Change.log">change
	log</ulink> for a revision history.</para>

    </abstract>
  </bookinfo>

  <dedication>
    <para>For Anita, the source of all the magic</para>
  </dedication>



  <part label="Part 1" id="part1">
    <title>Introduction</title>

  <partintro>  

    <para>The shell is a command interpreter. More than just the
      insulating layer between the operating system kernel and the user,
      it's also a fairly powerful programming language.  A shell program,
      called a <emphasis>script</emphasis>, is an easy-to-use tool for
      building applications by <quote>gluing</quote> together system
      calls, tools, utilities, and compiled binaries.  Virtually the
      entire repertoire of UNIX commands, utilities, and tools is
      available for invocation by a shell script.  If that were
      not enough, internal shell commands, such as testing and loop
      constructs, give additional power and flexibility to scripts.
      Shell scripts lend themselves exceptionally well to administrative
      system tasks and other routine repetitive jobs not requiring the
      bells and whistles of a full-blown tightly structured programming
      language.</para>

  </partintro>  

  <chapter id="why-shell">
    <title>Why Shell Programming?</title>
    
    
    <para>A working knowledge of shell scripting is essential to anyone
      wishing to become reasonably proficient at system administration,
      even if they do not anticipate ever having to actually write a
      script. Consider that as a Linux machine boots up, it executes the
      shell scripts in <filename class="directory">/etc/rc.d</filename>
      to restore the system configuration and set up services. A detailed
      understanding of these startup scripts is important for analyzing
      the behavior of a system, and possibly modifying it.</para>

    <para>Writing shell scripts is not hard to learn, since the scripts
      can be built in bite-sized sections and there is only a fairly
      small set of shell-specific operators and options
     
      <footnote><para>These are referred to as <link
        linkend="builtinref">builtins</link>, features internal to the
        shell.</para></footnote>

      to learn.  The syntax is simple and straightforward, similar to
      that of invoking and chaining together utilities at the command
      line, and there are only a few <quote>rules</quote> to learn.
      Most short scripts work right the first time, and debugging even
      the longer ones is straightforward.</para>

    <para>A shell script is a <quote>quick and dirty</quote> method of
      prototyping a complex application.  Getting even a limited subset
      of the functionality to work in a shell script, even if slowly,
      is often a useful first stage in project development. This way,
      the structure of the application can be tested and played with,
      and the major pitfalls found before proceeding to the final coding
      in C, C++, Java, or Perl.</para>

    <para>Shell scripting hearkens back to the classical UNIX philosophy
      of breaking complex projects into simpler subtasks, of chaining
      together components and utilities. Many consider this a better,
      or at least more esthetically pleasing approach to problem solving
      than using one of the new generation of high powered all-in-one
      languages, such as Perl, which attempt to be all things to all
      people, but at the cost of forcing you to alter your thinking
      processes to fit the tool.</para>

    <para>When not to use shell scripts

      <itemizedlist>
	<listitem>
	  <para>resource-intensive tasks, especially where speed is
	    a factor (sorting, hashing, etc.)</para>
	</listitem> <listitem>
	  <para>procedures involving heavy-duty math operations,
	    especially floating point arithmetic, arbitrary precision
	    calculations, or complex numbers (use C++ or FORTRAN
	    instead)</para>
	</listitem> <listitem>
	  <para>cross-platform portability required (use C instead)</para>
	</listitem> <listitem>
	  <para>complex applications, where structured programming is
	    a necessity (need type-checking of variables, function
	    prototypes, etc.)</para>
	</listitem> <listitem>
	  <para>mission-critical applications upon which you are betting the
	    ranch, or the future of the company</para>
	</listitem> <listitem>
	  <para>situations where security is important, where you need to
	    guarantee the integrity of your system and protect against
	    intrusion, cracking, and vandalism</para>
	</listitem> <listitem>
	  <para>project consists of subcomponents with interlocking
	    dependencies</para>
	</listitem> <listitem>
	  <para>extensive file operations required (Bash is limited to
	    serial file access, and that only in a particularly clumsy
	    and inefficient line-by-line fashion)</para>
	</listitem> <listitem>
	  <para>need multi-dimensional arrays</para>
	</listitem> <listitem>
	  <para>need data structures, such as linked lists or trees</para>
	</listitem> <listitem>
	  <para>need to generate or manipulate graphics or GUIs</para>
	</listitem> <listitem>
	  <para>need direct access to system hardware</para>
	</listitem> <listitem>
	  <para>need port or socket I/O</para>
	</listitem> <listitem>
	  <para>need to use libraries or interface with legacy code</para>
	</listitem> <listitem>
	  <para>proprietary, closed-source applications (shell scripts put the
	    source code right out in the open for all the world to see)</para>
	    
	</listitem>
      </itemizedlist></para>

    <para>If any of the above applies, consider a more powerful scripting
      language, perhaps Perl, Tcl, Python, Ruby, or possibly a high-level
      compiled language such as C, C++, or Java. Even then, prototyping
      the application as a shell script might still be a useful
      development step.</para>

    <para>We will be using Bash, an acronym for <quote>Bourne-Again
      Shell</quote> and a pun on Stephen Bourne's now classic Bourne
      Shell.  Bash has become a <foreignphrase>de facto</foreignphrase>
      standard for shell scripting on all flavors of UNIX. Most of
      the principles dealt with in this book apply equally well to
      scripting with other shells, such as the Korn Shell, from which
      Bash derives some of its features,

       <footnote><para>Many of the features of <emphasis>ksh88</emphasis>,
	 and even a few from the updated <emphasis>ksh93</emphasis>
	 have been merged into Bash.</para></footnote>

      and the C Shell and its variants. (Note that C Shell programming
      is not recommended due to certain inherent problems, as pointed out
      in an October, 1993 <ulink
      url="http://www.etext.org/Quartz/computer/unix/csh.harmful.gz">Usenet
      post</ulink> by Tom Christiansen.)
      </para>

    <para>What follows is a tutorial on shell scripting. It relies
      heavily on examples to illustrate various features of the shell.
      The example scripts work -- they've been tested -- and some
      of them are even useful in real life. The reader can play with
      the actual working code of the examples in the source archive
      (<filename>scriptname.sh</filename>),

         <footnote><para>By convention, user-written shell scripts that are
	 Bourne shell compliant generally take a name with a
	 <filename>.sh</filename> extension.  System scripts, such as
	 those found in <filename class="directory">/etc/rc.d</filename>,
	 do not follow this guideline.</para></footnote>

      give them execute permission (<userinput>chmod u+rx
      scriptname</userinput>), then run them to see what happens.
      Should the source archive not be available, then cut-and-paste from
      the HTML, pdf, or text rendered versions. Be aware that some of
      the scripts below introduce features before they are explained,
      and this may require the reader to temporarily skip ahead for
      enlightenment.</para>

    <para>Unless otherwise noted, the author of this book wrote the
      example scripts that follow.</para>

  </chapter> <!-- Why Shell Programming? -->


  <chapter id="sha-bang">
    <title>Starting Off With a Sha-Bang</title>

    <para>In the simplest case, a script is nothing more than a list of system
      commands stored in a file. At the very least, this saves the
      effort of retyping that particular sequence of commands each time
      it is invoked.</para>

    <example id="ex1">
      <title><command>cleanup</command>: A script to clean up the log
      files in /var/log </title> <programlisting>&ex1;</programlisting>
    </example>

    <para>There is nothing unusual here, just a set of commands that
      could just as easily be invoked one by one from the command line on
      the console or in an xterm. The advantages of placing the commands
      in a script go beyond not having to retype them time and again. The
      script can easily be modified, customized, or generalized for a
      particular application.</para>

    <example id="ex2">
      <title><command>cleanup</command>: An enhanced
      and generalized version of above script.</title>
      <programlisting>&ex2;</programlisting>
    </example>

    <para>Since you may not wish to wipe out the entire system log, this variant of
      the first script keeps the last section of the message log intact. You
      will constantly discover ways of refining previously written scripts
      for increased effectiveness.</para>
    
    <para>The 
      <firstterm><indexterm>
	  <primary>sha-bang</primary>
	</indexterm>
	sha-bang</firstterm> 
      (<token>
	<indexterm>
	  <primary>#!</primary>
	</indexterm>
	#!</token>) at the head of a script
      tells your system that this file 
      is a set of commands to be fed to the command interpreter indicated.
      <anchor id="magnumref">The <token>#!</token> is actually a two-byte

        <footnote><para>Some flavors of UNIX (those based on 4.2BSD)
          take a four-byte magic number, requiring
          a blank after the <token>!</token> --
          <userinput>#! /bin/sh</userinput>.</para></footnote>

	<indexterm>
	  <primary>magic number</primary>
	</indexterm>
	<quote>magic number</quote>, a special marker that
	designates a file type, or in this case an executable
	shell script (see <userinput>man magic</userinput> for more
	details on this fascinating topic). Immediately following
	the <emphasis>sha-bang</emphasis> is a path name. This is the
	path to the program that interprets the commands in the script,
	whether it be a shell, a programming language, or a utility. This
	command interpreter then executes the commands in the script,
	starting at the top (line 1 of the script), ignoring comments.

	  <footnote>
	    <para>The <token>#!</token> line in a shell script
	      will be the first thing the command interpreter
	      (<command>sh</command> or <command>bash</command>)
	      sees. Since this line begins with a <token>#</token>,
	      it will be correctly interpreted as a comment when the
	      command interpreter finally executes the script. The
	      line has already served its purpose - calling the command
	      interpreter.</para>
	    <para>If, in fact, the script includes an
	      <emphasis>extra</emphasis> <token>#!</token> line, then
	      <command>bash</command> will interpret it as a comment.
	        <programlisting>#!/bin/bash

echo "Part 1 of script."
a=1

#!/bin/bash
# This does *not* launch a new script.

echo "Part 2 of script."
echo $a  # Value of $a stays at 1.</programlisting></para>
	   </footnote>

	</para>


    <para><programlisting>#!/bin/sh
#!/bin/bash
#!/usr/bin/perl
#!/usr/bin/tcl
#!/bin/sed -f
#!/usr/awk -f</programlisting></para>

    <para>Each of the above script header lines calls a different command
      interpreter, be it <filename>/bin/sh</filename>, the default shell
      (<command>bash</command> in a Linux system) or otherwise.

        <footnote>
	  <para>This allows some cute tricks.</para>
	  <para><programlisting>#!/bin/rm
# Self-deleting script.

# Nothing much seems to happen when you run this... except that the file disappears.

WHATEVER=65

echo "This line will never print (betcha!)."

exit $WHATEVER  # Doesn't matter. The script will not exit here.</programlisting></para>
      <para>Also, try starting a <filename>README</filename> file with a
        <userinput>#!/bin/more</userinput>, and making it executable.
        The result is a self-listing documentation file.</para>
	</footnote>

      Using <userinput>#!/bin/sh</userinput>, the default Bourne Shell
      in most commercial variants of UNIX, makes the script <link
      linkend="portabilityissues">portable</link> to non-Linux machines,
      though you may have to sacrifice a few Bash-specific features.
      The script will, however, conform to the
      <acronym>POSIX</acronym>
	 <footnote><para><emphasis role="strong">P</emphasis>ortable
	 <emphasis role="strong">O</emphasis>perating
	 <emphasis role="strong">S</emphasis>ystem <emphasis
	 role="bold">I</emphasis>nterface, an attempt to
	 standardize UNI<emphasis role="strong">X</emphasis>-like
	 OSes.</para></footnote>
      <command>sh</command> standard.</para>

    <para>Note that the path given at the <quote>sha-bang</quote> must
      be correct, otherwise an error message -- usually <quote>Command
      not found</quote> -- will be the only result of running the
      script.</para>

    <para><token>#!</token> can be omitted if the script consists only
      of a set of generic system commands, using no internal
      shell directives.  The second example, above, requires the
      initial <token>#!</token>, since the variable assignment line,
      <userinput>lines=50</userinput>, uses a shell-specific construct.
      Note again that <userinput>#!/bin/sh</userinput> invokes the default
      shell interpreter, which defaults to <filename>/bin/bash</filename>
      on a Linux machine.</para>


      <important>
      <para>This tutorial encourages a modular approach
	to constructing a script. Make note of and collect
	<quote>boilerplate</quote> code snippets that might be useful
	in future scripts. Eventually you can build a quite extensive
	library of nifty routines.  As an example, the following script
	prolog tests whether the script has been invoked with the correct
	number of parameters.</para>

	<para><programlisting>if [ $# -ne Number_of_expected args ]
then
  echo "Usage: `basename $0` whatever"
  exit $WRONG_ARGS
fi</programlisting>
      </para>
      </important>
  

    <sect1 id="invoking">
      <title>Invoking the script</title>
      <para>Having written the script, you can invoke it by <userinput>sh
	scriptname</userinput>,

	  <footnote><para>Caution: invoking a Bash script by <userinput>sh
	  scriptname</userinput> turns off Bash-specific extensions, and the
	  script may therefore fail to execute.</para></footnote>
	
	or alternatively <userinput>bash scriptname</userinput>. (Not
	recommended is using <userinput>sh &lt;scriptname</userinput>,
	since this effectively disables reading from
	<filename>stdin</filename> within the script.)	Much more
	convenient is to make the script itself directly executable with
	a <link linkend="chmodref">chmod</link>.

	<variablelist>
	  <varlistentry>
	    <term>Either:</term> <listitem>
	      <para><userinput>chmod 555 scriptname</userinput> (gives
	      everyone read/execute permission)
	        <footnote><para>A script needs <emphasis>read</emphasis>, as
		well as execute permission for it to run, since the shell
		needs to be able to read it.</para></footnote>
	      </para>
	    </listitem>
	  </varlistentry> <varlistentry>
	    <term>or</term> <listitem>
	      <para><userinput>chmod +rx scriptname</userinput> (gives
	      everyone read/execute permission)</para> <para><userinput>chmod
	      u+rx scriptname</userinput> (gives only the
		script owner read/execute permission)</para>
	    </listitem>
	  </varlistentry>
	</variablelist>
      </para>

      <para>Having made the script executable, you may now test it by
	<userinput>./scriptname</userinput>.
	
	  <footnote><para>Why not simply invoke the script with
	  <userinput>scriptname</userinput>? If the directory
	  you are in (<link linkend="pwdref">$PWD</link>) is where
	  <emphasis>scriptname</emphasis> is located, why doesn't this
	  work?  This fails because, for security reasons, the current
	  directory, <quote>.</quote> is not included in a user's <link
	  linkend="pathref">$PATH</link>. It is therefore necessary to
	  explicitly invoke the script in the current directory with
	  a <userinput>./scriptname</userinput>.</para></footnote>

	If it begins with a <quote>sha-bang</quote> line, invoking the
	script calls the correct command interpreter to run it.</para>

      <para>As a final step, after testing and debugging,
        you would likely want to move it to <filename
        class="directory">/usr/local/bin</filename> (as root, of
        course), to make the script available to yourself and all
        other users as a system-wide executable.  The script could
        then be invoked by simply typing <command>scriptname</command>
        <keycap>[ENTER]</keycap> from the command line.</para>

    </sect1> <!-- Invoking the script -->


    <sect1 id="prelimexer">
      <title>Preliminary Exercises</title>

      <orderedlist>

        <listitem>
	<para>System administrators often write scripts to automate common
	  tasks. Give several instances where such scripts would be
	  useful.</para>
	</listitem>  

	<listitem>  
	<para>Write a script that upon invocation shows the
	  <link linkend="dateref">time and date</link>, <link
	  linkend="whoref">lists all logged-in users</link>, and gives
	  the system <link linkend="uptimeref">uptime</link>. The script
	  then <link linkend="ioredirref">saves this information</link>
	  to a logfile.</para>
	</listitem>

      </orderedlist>

    </sect1> <!-- Preliminary Exercises -->

  </chapter> <!-- Starting Off With a Sha-Bang -->


  </part> <!-- Part 1 (Introduction) -->



  <part label="Part 2" id="part2">
    <title>Basics</title>



  <chapter id="special-chars">
    <title>Special Characters</title>

      <variablelist id="scharlist">
        <title><anchor id="scharlist1">Special Characters Found In
          Scripts and Elsewhere</title>

	<varlistentry><term><token>#</token></term>
	  <indexterm>
	    <primary>#</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>#</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>comment</primary>
	  </indexterm>	  
	  <listitem>
	    <formalpara><title>Comments</title>
	      <para>Lines beginning with a <token>#</token>
	      (<link linkend="magnumref">with the exception of
	      <token>#!</token></link>) are comments.</para>
	    </formalpara>

	    <para><programlisting># This line is a comment.</programlisting></para>

	    <para>Comments may also occur at the end of a command.</para>
	    
	    <para><programlisting>echo "A comment will follow." # Comment here.</programlisting></para>	    

	    <para>Comments may also follow <link
	    linkend="whitespaceref">whitespace</link> at the beginning
	    of a line.</para>

	    <para><programlisting>	# A tab precedes this comment.</programlisting></para>

	    <caution><para>A command may not follow a comment on the
	      same line. There is no method of terminating the comment,
	      in order for <quote>live code</quote> to begin on the same
	      line. Use a new line for the next command.</para></caution>

	    <note><para>Of course, an escaped <token>#</token> in an
	    <command>echo</command> statement does
	    <emphasis>not</emphasis> begin a comment. Likewise, a
	    <token>#</token> appears in <link linkend="psub2">certain parameter
	    substitution constructs</link> and in <link linkend="numconstants">
	    numerical constant expressions</link>.

	    <programlisting>echo "The # here does not begin a comment."
echo 'The # here does not begin a comment.'
echo The \# here does not begin a comment.
echo The # here begins a comment.

echo ${PATH#*:}       # Parameter substitution, not a comment.
echo $(( 2#101011 ))  # Base conversion, not a comment.

# Thanks, S.C.</programlisting>

	  The standard <link linkend="quotingref">quoting and
	  escape</link> characters (&quot; ' \) escape the #.
	  </para></note>

	  <para>Certain <link linkend="psorex1">pattern matching
	    operations</link> also use the <token>#</token>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry><term><token>;</token></term>
	  <indexterm>
	    <primary>;</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>;</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>separator</primary>
	  </indexterm>	  
	  
	  <listitem>
	    <formalpara><title>Command separator</title>
	      <para>[Semicolon]  Permits putting two or more commands on
	      the same line.</para>
	    </formalpara>

	    <para>
	      <programlisting>echo hello; echo there


if [ -x "$filename" ]; then    # Note that "if" and "then" need separation.
                               # Why?
  echo "File $filename exists."; cp $filename $filename.bak
else
  echo "File $filename not found."; touch $filename
fi; echo "File test complete."</programlisting>
</para>
	    
	    <para>Note that the <quote><token>;</token></quote> sometimes
	      needs to be <link linkend="escp">escaped</link>.</para>

	    </listitem>
	</varlistentry>

	<varlistentry><term><token>;;</token></term>
	  <indexterm>
	    <primary>;;</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>case</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>;;</primary>
	  </indexterm>	  
	  
	  <listitem>
	    <formalpara><title>Terminator in a <link
	      linkend="caseesac1">case</link> option</title>
	      <para>[Double semicolon]</para>
	    </formalpara>

	    <para><programlisting>case "$variable" in
abc)  echo "$variable = abc" ;;
xyz)  echo "$variable = xyz" ;;
esac</programlisting></para>

	    </listitem>
	</varlistentry>


	<varlistentry><term><token>.</token></term>
	  <indexterm>
	    <primary>.</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>.</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>dot command</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>source</primary>
	  </indexterm>	  

	  <listitem>
	    <para><anchor id="dotref"></para>
	    <formalpara><title><quote>dot</quote> command</title>
	      <para>[period]  Equivalent to <link
		linkend="sourceref">source</link> (see
		<xref linkend="ex38">). This is a bash <link
		linkend="builtinref">builtin</link>.</para>
	    </formalpara>

	    </listitem>
	</varlistentry>


	<varlistentry><term><token>.</token></term>
	  <indexterm>
	    <primary>.</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>.</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>filename</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>part of a filename</primary>
	  </indexterm>	  

	  <listitem>
	    <formalpara><title><quote>dot</quote>, as a component of a filename</title>
              <para>When working with filenames, a dot is the prefix
		of a <quote>hidden</quote> file, a file that an
		<link linkend="lsref">ls</link> will not normally show.
	        <screen><prompt>bash$ </prompt><userinput>touch .hidden-file</userinput>
<prompt>bash$ </prompt><userinput>ls -l</userinput>	      
<computeroutput>total 10
 -rw-r--r--    1 bozo      4034 Jul 18 22:04 data1.addressbook
 -rw-r--r--    1 bozo      4602 May 25 13:58 data1.addressbook.bak
 -rw-r--r--    1 bozo       877 Dec 17  2000 employment.addressbook</computeroutput>


<prompt>bash$ </prompt><userinput>ls -al</userinput>	      
<computeroutput>total 14
 drwxrwxr-x    2 bozo  bozo      1024 Aug 29 20:54 ./
 drwx------   52 bozo  bozo      3072 Aug 29 20:51 ../
 -rw-r--r--    1 bozo  bozo      4034 Jul 18 22:04 data1.addressbook
 -rw-r--r--    1 bozo  bozo      4602 May 25 13:58 data1.addressbook.bak
 -rw-r--r--    1 bozo  bozo       877 Dec 17  2000 employment.addressbook
 -rw-rw-r--    1 bozo  bozo         0 Aug 29 20:54 .hidden-file</computeroutput>
	        </screen>
	      </para>
	    </formalpara>

	      <para>When considering directory names, <emphasis>a single
		dot</emphasis> represents the current working directory,
		and <emphasis>two dots</emphasis> denote the parent
		directory.</para>

	      <para>
	        <screen>
<prompt>bash$ </prompt><userinput>pwd</userinput>
<computeroutput>/home/bozo/projects</computeroutput>

<prompt>bash$ </prompt><userinput>cd .</userinput>
<prompt>bash$ </prompt><userinput>pwd</userinput>
<computeroutput>/home/bozo/projects</computeroutput>

<prompt>bash$ </prompt><userinput>cd ..</userinput>
<prompt>bash$ </prompt><userinput>pwd</userinput>
<computeroutput>/home/bozo/</computeroutput>
	        </screen>
	      </para>

	      <para>The <emphasis>dot</emphasis> often appears as the
	        destination (directory) of a file movement command.</para>
	      
	      <para>
	        <screen>
<prompt>bash$ </prompt><userinput>cp /home/bozo/current_work/junk/* .</userinput>
	        </screen>
	      </para>

	  </listitem>
	</varlistentry>


	<varlistentry><term><token>.</token></term>
	  <indexterm>
	    <primary>.</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>.</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>character match</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>match single character</primary>
	  </indexterm>	  

	  <listitem>
	    <formalpara><title><quote>dot</quote> character match</title>
	      <para>When <link linkend="regexdot">matching
	        characters</link>, as part of a <link
	        linkend="regexref">regular expression</link>, a
	        <quote>dot</quote> matches a single character.</para>
	    </formalpara>

	    </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>"</token></term>
	  <listitem><formalpara><title><link linkend="dblquo">partial
	    quoting</link></title>
	      <para>[double quote]  <emphasis>"STRING"</emphasis>
		preserves (from interpretation) most of the special
		characters within <emphasis>STRING</emphasis>. See also
		<xref linkend="quoting">.</para>
	    </formalpara> </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>'</token></term>
	  <listitem><formalpara><title><link linkend="snglquo">full
	    quoting</link></title>
	      <para>[single quote]  <emphasis>'STRING'</emphasis>
		preserves all special characters within
		<emphasis>STRING</emphasis>. This is a stronger form
		of quoting than using <token>"</token>.  See also <xref
		linkend="quoting">.</para>
	    </formalpara> </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>,</token></term>
	  <listitem><formalpara><title><link linkend="commaop">comma
	    operator</link></title>
	      <para>The <command>comma operator</command> links together a
	        series of arithmetic operations. All are evaluated, but only
		the last one is returned.
               <programlisting>let "t2 = ((a = 9, 15 / 3))"  # Set "a" and calculate "t2".</programlisting>
	      </para> 
	    </formalpara> </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>\</token></term>
	  <listitem><formalpara><title><link linkend="escp">escape</link></title>
	      <para>[backslash]  <userinput>\X</userinput>
		<quote>escapes</quote> the character
		<emphasis>X</emphasis>. This has the effect of
		<quote>quoting</quote> <emphasis>X</emphasis>, equivalent
		to <emphasis>'X'</emphasis>.  The <token>\</token> may
		be used to quote <token>"</token> and <token>'</token>,
		so they are expressed literally.</para>
	    </formalpara>
	      <para>See <xref linkend="quoting"> for an in-depth explanation
	        of escaped characters.</para>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>/</token></term>
	  <listitem><formalpara><title>Filename path separator</title>
	      <para>[forward slash] Separates
	        the components of a filename (as in
	        <filename>/home/bozo/projects/Makefile</filename>).</para>
	    </formalpara>
	    <para>This is also the division <link
	      linkend="arops1">arithmetic operator</link>.</para>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>`</token></term>
	  <listitem><formalpara><title><link
	  linkend="commandsubref">command substitution</link></title>
	      <para>[backticks]  <emphasis>`command`</emphasis> makes
		available the output of <emphasis>command</emphasis>
		for setting a variable. This is also known as
		<link linkend="backquotesref">backticks</link> or
		backquotes.</para></formalpara> </listitem>
	</varlistentry>

	<varlistentry><term><token>:</token></term>
	  <indexterm>
	    <primary>:</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>:</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>null command</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>true</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>endless loop</primary>
	  </indexterm>	  

	  <listitem>
	    <para><anchor id="nullref"></para>
	    <formalpara><title>null command</title>
	      <para>[colon]  This is the shell equivalent of a
		<quote>NOP</quote> (<replaceable>no op</replaceable>, a
		do-nothing operation). It may be considered a synonym for
		the shell builtin <link linkend="trueref">true</link>. The
		<quote><token>:</token></quote> command is a itself a Bash
		builtin, and its <link linkend="exitstatusref">exit
		status</link> is <quote>true</quote>
		(<returnvalue>0</returnvalue>).</para>
	    </formalpara>

	    <para><programlisting>:
echo $?   # 0</programlisting></para>


	    <para>Endless loop:</para>

	    <para><programlisting>
while :
do
   operation-1
   operation-2
   ...
   operation-n
done

# Same as:
#    while true
#    do
#      ...
#    done</programlisting>
	    </para>

	    <para>Placeholder in if/then test:</para>

	    <para><programlisting>
if condition
then :   # Do nothing and branch ahead
else
   take-some-action
fi</programlisting>
	    </para>

	    <para>Provide a placeholder where a binary operation is
	      expected, see <xref linkend="arithops"> and <link
	      linkend="defparam">default parameters</link>.</para>

	    <para><programlisting>: ${username=`whoami`}
# ${username=`whoami`}   without the leading : gives an error
#                        unless "username" is a command or builtin...</programlisting>
</para>

	    <para>Provide a placeholder where a command is expected in a
	      <link linkend="heredocref">here document</link>. See <xref
	      linkend="anonheredoc">.</para>

	    <para>Evaluate string of variables using
		<link linkend="paramsubref">parameter substitution</link>
		(as in <xref linkend="ex6">).

	    <programlisting>: ${HOSTNAME?} ${USER?} ${MAIL?}
#Prints error message if one or more of essential environmental variables not set.</programlisting>
</para>
            
            <para><command><link linkend="exprepl1">Variable expansion / substring
	      replacement</link></command>.</para>
	    
	    <para>In combination with the <token>&gt;</token> <link
	      linkend="ioredirref">redirection operator</link>,
	      truncates a file to zero length, without changing its
	      permissions. If the file did not previously exist,
	      creates it.

	      <programlisting>: > data.xxx   # File "data.xxx" now empty.	      

# Same effect as   cat /dev/null >data.xxx
# However, this does not fork a new process, since ":" is a builtin.</programlisting>
              See also <xref linkend="ex12">.</para>

	    <para>In combination with the <token>&gt;&gt;</token>
	      redirection operator, updates a file access/modification
	      time (<userinput>: &gt;&gt; new_file</userinput>).
	      If the file did not previously exist, creates it.  This is
	      equivalent to <link linkend="touchref">touch</link>.</para>

	    <note><para>This applies to regular files, not pipes,
	      symlinks, and certain special files.</para></note>


	    <para>May be used to begin a comment line, although this is not
	      recommended. Using <token>#</token> for a comment turns
	      off error checking for the remainder of that line, so
	      almost anything may be appear in a comment. However,
	      this is not the case with
	      <token>:</token>.
	      <programlisting>: This is a comment that generates an error, ( if [ $x -eq 3] ).</programlisting>
	    </para>

	    <para>The <quote><token>:</token></quote> also serves as a field
	      separator, in <filename>/etc/passwd</filename>, and in the <link
	      linkend="pathref">$PATH</link> variable.
	      <screen><prompt>bash$ </prompt><userinput>echo $PATH</userinput>
<computeroutput>/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games</computeroutput></screen>
	    </para>



	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>!</token></term>
	  <indexterm>
	    <primary>!</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>!</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>not</primary>
	    <secondary>logical</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>not</primary>
	  </indexterm>	  

	  <listitem>
	  <para><anchor id="notref"></para>
	  <formalpara><title>reverse (or negate) the sense of
	  a test or exit status</title>

	      <para>The <token>!</token> operator inverts the <link
		linkend="exitstatusref">exit status</link>
		of the command to which it is applied (see
		<xref linkend="negcond">). It also inverts
		the meaning of a test operator. This can, for
		example, change the sense of <quote>equal</quote>
		( <link linkend="equalsignref">=</link>
		) to <quote>not-equal</quote> ( != ). The
		<token>!</token> operator is a Bash <link
		linkend="keywordref">keyword</link>.</para>

	    </formalpara>
	      <para>In a different context, the <token>!</token>
	        also appears in <link linkend="ivr2">indirect variable
		references</link>.</para>

	      <para>In yet another context, from the <emphasis>command
		line</emphasis>, the <token>!</token> invokes the
		Bash <emphasis>history mechanism</emphasis> (see <xref
		linkend="histcommands">). Note that within a script,
		the history mechanism is disabled.</para>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>*</token></term>
	  <indexterm>
	    <primary>*</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>*</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>wild card</primary>
	    <secondary>globbing</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>regular expression</primary>
	  </indexterm>	  

	  <listitem><formalpara><title>wild card</title>

	      <para>[asterisk]	The <token>*</token> character serves
		as a <quote>wild card</quote> for filename expansion in
		<link linkend="globbingref">globbing</link>. By itself,
		it matches every filename in a given directory.</para>
	    </formalpara>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>echo *</userinput>
<computeroutput>abs-book.sgml add-drive.sh agram.sh alias.sh</computeroutput>
	      </screen>
	    </para>
		
	      <para>The <token>*</token> also represents any number
	      (or zero) characters in a <link
		linkend="regexref">regular expression</link>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>*</token></term>
	  <indexterm>
	    <primary>*</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>*</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>multiplication</primary>
	    <secondary>exponentiation</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>arithmetic operator</primary>
	  </indexterm>	  

	  <listitem><formalpara><title><link linkend="arops1">arithmetic operator</link></title>

	      <para>In the context of arithmetic operations, the
	        <token>*</token> denotes multiplication.</para>

	    </formalpara>

	      <para>A double asterisk, <token>**</token>, is the <link
	        linkend="exponentiationref">exponentiation
	        operator</link>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>?</token></term>
	  <indexterm>
	    <primary>?</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>?</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>test</primary>
	    <secondary>operator</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>test token</primary>
	  </indexterm>	  

	  <listitem><formalpara><title>test operator</title>
	      <para>Within certain expressions, the <token>?</token> indicates
	        a test for a condition.</para>
	    </formalpara>

	      <para>In a <link linkend="dblparens">double
	        parentheses construct</link>, the <token>?</token> serves
		as a C-style trinary operator. See <xref
		linkend="cvars">.</para>

              <para>In a <link linkend="paramsubref">parameter
	        substitution</link> expression, the <token>?</token>
		<link linkend="qerrmsg">tests whether a variable has been
		set</link>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>?</token></term>
	  <indexterm>
	    <primary>?</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>?</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>wild card</primary>
	    <secondary>globbing</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>regular expression</primary>
	  </indexterm>	  

	  <listitem><formalpara><title>wild card</title>

	      <para>The <token>?</token> character serves as a
		single-character <quote>wild card</quote> for filename
		expansion in <link linkend="globbingref">globbing</link>,
		as well as <link linkend="quexregex">representing one
		character</link> in an <link linkend="extregex">extended
		regular expression</link>.</para>

	    </formalpara>

	  </listitem>
	</varlistentry>

	<varlistentry><term><token>$</token></term>
	  <indexterm>
	    <primary>$</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>$</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>variable substitution</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title><link linkend="varsubn">Variable
              substitution</link></title>
             <para>
	       <programlisting>var1=5
var2=23skidoo

echo $var1     # 5
echo $var2     # 23skidoo</programlisting>
	       </para>
	       </formalpara>

	       <para>A <token>$</token> prefixing a variable name
		indicates the <emphasis>value</emphasis> the variable
		holds.</para>

	  </listitem>
	</varlistentry>  

	<varlistentry><term><token>$</token></term>
	  <indexterm>
	    <primary>$</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>$</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>regular expression</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>end of line</primary>
	  </indexterm>	  

	  <listitem>
	    <formalpara><title>end-of-line</title>
	      <para>In a <link linkend="regexref">regular expression</link>, a
	        <quote>$</quote> addresses the end of a line of text.</para>
	    </formalpara>

	    </listitem>
	</varlistentry>

	<varlistentry><term><token>${}</token></term>
	  <indexterm>
	    <primary>${}</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>${}</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>parameter substitution</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title><link linkend="paramsubref">Parameter
              substitution</link></title>
             <para></para></formalpara>
	  </listitem>
	</varlistentry>  

	<varlistentry>
	  <term><token>$*</token></term>
	  <term><token>$@</token></term>
	  <indexterm>
	    <primary>$*</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>$*</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>$@</primary>
	    <secondary>positional parameters</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>$@</primary>
	  </indexterm>	  

	  <listitem><formalpara><title><link linkend="appref">positional
	    parameters</link></title>
	      <para></para>
	    </formalpara>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>$?</token></term>
	  <indexterm>
	    <primary>$?</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>?</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>exit status</primary>
	    <secondary>variable</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>exit status</primary>
	  </indexterm>	  

	  <listitem><formalpara><title>exit status variable</title>
	      <para>The <link linkend="exsref">$? variable</link>
	        holds the <link linkend="exitstatusref">exit status</link>
		of a command, a <link linkend="functionref">function</link>,
		or of the script itself.</para>
	    </formalpara>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>$$</token></term>
	  <indexterm>
	    <primary>$$</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>$$</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>process id</primary>
	    <secondary>variable</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>process id</primary>
	  </indexterm>	  

	  <listitem><formalpara><title>process id variable</title>
	      <para>The <link linkend="proccid">$$ variable</link>
	        holds the <emphasis>process id</emphasis> of the script in
		which it appears.</para>
	    </formalpara>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>()</token></term>

	  <listitem><formalpara><title>command group</title>
	      <para><programlisting>(a=hello; echo $a)</programlisting></para>
	    </formalpara>

	  <important>
	  
	    <para>A listing of commands within
	      <replaceable>parentheses</replaceable> starts a <link
	      linkend="subshellsref">subshell</link>.</para>

	    <para>Variables inside parentheses, within the subshell, are not
	      visible to the rest of the script. The parent process,
	      the script, <link linkend="parvis">cannot read variables
	      created in the child process</link>, the subshell.
	      <programlisting>a=123
( a=321; )	      

echo "a = $a"   # a = 123
# "a" within parentheses acts like a local variable.</programlisting></para>
	  </important>


	  <formalpara><title>array initialization</title>
	    <para><programlisting>Array=(element1 element2 element3)</programlisting></para>
	    </formalpara>
	  </listitem>

	</varlistentry>

	<varlistentry>
	  <indexterm>
	    <primary>{xxx,yyy,zzz..}</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>{}</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>brace expansion</primary>
	  </indexterm>	  
	  <term><token>{xxx,yyy,zzz,...}</token></term>
	  <listitem><formalpara><title>Brace expansion</title>
	      <para><programlisting>grep Linux file*.{txt,htm*}
# Finds all instances of the word "Linux"
# in the files "fileA.txt", "file2.txt", "fileR.html", "file-87.htm", etc.</programlisting></para>
	    </formalpara>
	  <para>A command may act upon a comma-separated list of file specs within
	  <replaceable>braces</replaceable>.

	     <footnote><para>The shell does the <emphasis>brace
	       expansion</emphasis>. The command itself acts upon the
	       <emphasis>result</emphasis> of the expansion.</para></footnote>
	  
	  Filename expansion (<link linkend="globbingref">globbing</link>)
	  applies to the file specs between the braces.</para>

	  <caution>
	    <para>No spaces allowed within the braces
	    <emphasis>unless</emphasis> the spaces are quoted or escaped.</para>
	    
	    <para><userinput>echo {file1,file2}\ :{\ A," B",' C'}</userinput></para>
	    <para><computeroutput>file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C</computeroutput></para>

	   </caution>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>{}</token></term>
	  <indexterm>
	    <primary>{}</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>{}</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>block of code</primary>
	  </indexterm>	  

	  <listitem>
	  <para><anchor id="codeblockref"></para>
	  <formalpara><title>Block of code</title>
	      <para>[curly brackets]	Also referred to as an
		<quote>inline group</quote>, this construct, in effect,
		creates an anonymous function. However, unlike a <link
		linkend="functionref">function</link>, the variables
		in a code block remain visible to the remainder of the
		script.</para></formalpara>
	      
	      <para>
	      <screen><prompt>bash$ </prompt><userinput>{ local a; a=123; }</userinput>
<computeroutput>bash: local: can only be used in a function</computeroutput>
	      </screen>
	      </para>

	      <para><programlisting>a=123
{ a=321; }
echo "a = $a"   # a = 321   (value inside code block)

# Thanks, S.C.</programlisting></para>


	    <para>The code block enclosed in braces may have <link
	      linkend="ioredirref">I/O redirected</link> to and from
	      it.</para>

	    <example id="ex8">
	      <title>Code blocks and I/O redirection</title>
	      <programlisting>&ex8;</programlisting>
	    </example>

	    <example id="rpmcheck">
	      <title>Saving the results of a code block to a file</title>
	      <programlisting>&rpmcheck;</programlisting>
	    </example>

	    <note><para>Unlike a command group within (parentheses),
	      as above, a code block enclosed by {braces} will
	      <emphasis>not</emphasis> normally launch a <link
	      linkend="subshellsref">subshell</link>.

		<footnote><para>Exception: a code block in braces as
		  part of a pipe <emphasis>may</emphasis> be run as a
		  <link linkend="subshellsref">subshell</link>.

		<programlisting>ls | { read firstline; read secondline; }
# Error. The code block in braces runs as a subshell,
# so the output of "ls" cannot be passed to variables within the block.
echo "First line is $firstline; second line is $secondline"  # Will not work.

# Thanks, S.C.</programlisting></para></footnote>

	      </para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>{} \;</token></term>
	  <listitem>

	  <formalpara><title>pathname</title>
	      <para>Mostly used in <link linkend="findref">find</link>
		constructs.  This is <emphasis>not</emphasis> a shell
		<link linkend="builtinref">builtin</link>.</para>
	    </formalpara>

	      <note><para>The <quote><token>;</token></quote> ends
		the <option>-exec</option> option of a
		<command>find</command> command sequence.  It needs
		to be escaped to protect it from interpretation by the
		shell.</para></note>

	  </listitem>
	</varlistentry>


	<varlistentry><term><token>[ ]</token></term>
	  <indexterm>
	    <primary>[]</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>[ ]</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>test</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title>test</title>
             <para></para></formalpara>
	     <para><anchor id="leftbracket"><link
	       linkend="ifthen">Test</link> expression between <command>[
	       ]</command>.  Note that <command>[</command> is part of
	       the shell builtin <command>test</command> (and a synonym
	       for it), <emphasis>not</emphasis> a link to the external
	       command <filename>/usr/bin/test</filename>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>[[ ]]</token></term>
	  <indexterm>
	    <primary>[[]]</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>[[ ]]</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>test</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title>test</title>
             <para></para></formalpara>
	     <para>Test expression between <token>[[ ]]</token> (shell
	       <link linkend="keywordref">keyword</link>).</para>
	     <para>See the discussion on the <link
	     linkend="dblbrackets">[[ ... ]] construct</link>.</para> 
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>[ ]</token></term>
	  <indexterm>
	    <primary>[ ]</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>array_element[ ]</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>array element</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title>array element</title>
             <para></para></formalpara>
	     <para>In the context of an <link linkend="arrayref">array</link>,
	       brackets set off the numbering of each element of that array.
	         <programlisting>Array[1]=slot_1
echo ${Array[1]}</programlisting></para>		 
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>[ ]</token></term>
	  <indexterm>
	    <primary>[ ]</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>character range</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>regular expression</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title>range of characters</title>
             <para></para></formalpara>
	     <para>As part of a <link linkend="regexref">regular
	       expression</link>, brackets delineate a <link
	       linkend="bracketsref">range of characters</link> to
	       match.</para>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>(( ))</token></term>
	  <indexterm>
	    <primary>(( ))</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>(( ))</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>integer comparison</primary>
	  </indexterm>	  
	  <listitem>
            <formalpara><title>integer expansion</title>
             <para></para></formalpara>
	     <para>Expand and evaluate integer expression between
	       <token>(( ))</token>.</para>
	     <para>See the discussion on the <link
	     linkend="dblparens">(( ... )) construct</link>.</para>
	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>></token> <token>&></token> <token>>&</token> <token>>></token> <token><</token></term>
	  <indexterm>
	    <primary>></primary>
	  </indexterm>
	  <indexterm>
	    <primary>>&</primary>
	  </indexterm>
	  <indexterm>
	    <primary>>></primary>
	  </indexterm>
	  <indexterm>
	    <primary><</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>></secondary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>>&</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>>></secondary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary><</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>redirection</primary>
	  </indexterm>	  

	  <listitem><formalpara><title><link linkend="ioredirref">redirection</link></title>
	      <para></para>
	    </formalpara>

	    <para><userinput>scriptname >filename</userinput> redirects the output of
	      <filename>scriptname</filename> to file
	      <filename>filename</filename>. Overwrite
	      <filename>filename</filename> if it already exists.</para>

	    <para><userinput>command &>filename</userinput> redirects
	      both the <filename>stdout</filename> and the
	      <filename>stderr</filename> of <filename>command</filename>
	      to <filename>filename</filename>.</para>

	    <para><userinput>command >&2</userinput> redirects
	      <filename>stdout</filename> of <filename>command</filename>
	      to <filename>stderr</filename>.</para>

	    <para><userinput>scriptname >>filename</userinput> appends
	    the output of <filename>scriptname</filename>
	    to file <filename>filename</filename>. If
	    <filename>filename</filename> does not already exist,
	    it will be created.</para>


	    <formalpara><title><link linkend="processsubref">process substitution</link></title>
	      <para></para>
	    </formalpara>

	    <para><userinput>(command)></userinput></para>
	    <para><userinput><(command)</userinput></para>


	    <para><link linkend="ltref">In a different context</link>,
	      the <quote><token>&lt;</token></quote> and
	      <quote><token>&gt;</token></quote> characters act
	      as <link linkend="scomparison1">string comparison
	      operators</link>.</para>

	    <para><link linkend="intlt">In yet another context</link>,
	      the <quote><token>&lt;</token></quote> and
	      <quote><token>&gt;</token></quote> characters act
	      as <link linkend="icomparison1">integer comparison
	      operators</link>. See also <xref linkend="ex45">.</para>

	  </listitem>


	</varlistentry>

	<varlistentry>
	  <term><token><<</token></term>
	  <listitem><formalpara><title>redirection used in a <link
	    linkend="heredocref">here document</link></title>
	      <para></para>
	    </formalpara>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token><</token></term>
	  <term><token>></token></term>
	  <indexterm>
	    <primary><</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary><</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>></primary>
	    <secondary>ASCII comparison</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>></primary>
	  </indexterm>	  

	  <listitem><formalpara><title><link linkend="ltref">ASCII
	    comparison</link></title>
	      <para><programlisting>veg1=carrots
veg2=tomatoes

if [[ "$veg1" < "$veg2" ]]
then
  echo "Although $veg1 precede $veg2 in the dictionary,"
  echo "this implies nothing about my culinary preferences."
else
  echo "What kind of dictionary are you using, anyhow?"
fi</programlisting></para>
	    </formalpara>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>\<</token></term>
	  <term><token>\></token></term>
	  <indexterm>
	    <primary>\<</primary>
	  </indexterm>
	  <indexterm>
	    <primary>regular expression</primary>
	    <secondary>\<</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>></primary>
	    <secondary>word boundary</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>></primary>
	  </indexterm>	  

	  <listitem><formalpara><title><link linkend="anglebrac">word
	    boundary</link> in a <link linkend="regexref">regular
	    expression</link></title>
	    <para></para>
	    </formalpara>
	      <para><prompt>bash$ </prompt><userinput>grep '\&lt;the\&gt;' textfile</userinput></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>|</token></term>
	  <indexterm>
	    <primary>|</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>|</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>pipe</primary>
	  </indexterm>	  

	  <listitem>
	  <para><anchor id="piperef"></para>
	  <formalpara><title>pipe</title>
	      <para>Passes the output of previous command to the input
		of the next one, or to the shell. This is a method of
		chaining commands together.</para>
	    </formalpara>

	    <para>
              <programlisting>echo ls -l | sh
#  Passes the output of "echo ls -l" to the shell,
#+ with the same result as a simple "ls -l".


cat *.lst | sort | uniq
# Merges and sorts all ".lst" files, then deletes duplicate lines.</programlisting>
	    </para>

	    <sidebar>
	    <para>A pipe, as a classic method of interprocess
	      communication, sends the <filename>stdout</filename>
	      of one process to the <filename>stdin</filename>
	      of another.  In a typical case, a command,
	      such as <link linkend="catref">cat</link> or <link
	      linkend="echoref">echo</link>, pipes a stream of data to a
	      <quote>filter</quote> (a command that transforms its input)
	      for processing.</para>
	    <para>  
	      <userinput>cat $filename | grep $search_word</userinput>
            </para>
	    </sidebar>


	    <para><anchor id="ucref">The output of a command or commands
	      may be piped to a script.

	      <programlisting>#!/bin/bash
# uppercase.sh : Changes input to uppercase.

tr 'a-z' 'A-Z'
#  Letter ranges must be quoted
#+ to prevent filename generation from single-letter filenames.

exit 0</programlisting>
              Now, let us pipe the output of <command>ls -l</command> to this
	      script.

	      <screen><prompt>bash$ </prompt><userinput>ls -l | ./uppercase.sh</userinput>
<computeroutput>-RW-RW-R--    1 BOZO  BOZO       109 APR  7 19:49 1.TXT
 -RW-RW-R--    1 BOZO  BOZO       109 APR 14 16:48 2.TXT
 -RW-R--R--    1 BOZO  BOZO       725 APR 20 20:56 DATA-FILE</computeroutput>
	      </screen>
	    </para>

	     <note>

	     <para>The <filename>stdout</filename> of each process in
	       a pipe must be read as the <filename>stdin</filename>
	       of the next. If this is not the case, the data stream
	       will <emphasis>block</emphasis>, and the pipe will not
	       behave as expected.
	         <programlisting>cat file1 file2 | ls -l | sort
# The output from "cat file1 file2" disappears.</programlisting>
             </para>

	     <para>A pipe runs as a <link linkend="childref">child
	       process</link>, and therefore cannot alter script
	       variables.
	         <programlisting>variable="initial_value"
echo "new_value" | read variable
echo "variable = $variable"     # variable = initial_value</programlisting>
             </para>

	     <para>If one of the commands in the pipe
	       aborts, this prematurely terminates execution of the
	       pipe. Called a <emphasis>broken pipe</emphasis>, this
	       condition sends a <emphasis>SIGPIPE</emphasis> <link
	       linkend="signald">signal</link>.</para>

	      </note>


	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>>|</token></term>
	  <indexterm>
	    <primary>>|</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>>|</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>redirection</primary>
	    <secondary>force</secondary>
	  </indexterm>	  
	  <indexterm>
	    <primary>noclobber</primary>
	  </indexterm>	  

	  <listitem><formalpara><title>force redirection (even if
		the <link linkend="noclobberref">noclobber option</link>
		is set)</title>
	      <para>This will forcibly overwrite an existing file.</para>
	    </formalpara>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>||</token></term>
	  <indexterm>
	    <primary>||</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>||</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>or</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>logical operator</primary>
	  </indexterm>	  

	  <listitem>
	    <formalpara><title><link linkend="orref">OR logical operator</link></title>
	      <para>In a <link linkend="testconstructs1">test
		construct</link>, the <token>||</token> operator causes
		a return of <returnvalue>0</returnvalue> (success) if
		<emphasis>either</emphasis> of the linked test conditions
		is true.</para>
	    </formalpara>

	    </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>&amp;</token></term>
	  <listitem><formalpara><title>Run job in background</title>
	      <para>A command followed by an <token>&amp;</token>
	        will run in the background.</para>
	    </formalpara>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>sleep 10 &</userinput>
<computeroutput>[1] 850</computeroutput>
<computeroutput>[1]+  Done                    sleep 10</computeroutput>
	      </screen>
	    </para>

	    <para>Within a script, commands and even <link
	      linkend="forloopref1">loops</link> may run in the
	      background.</para>

	    <example id="bgloop">
	      <title>Running a loop in the background</title>
	      <programlisting>&bgloop;</programlisting>
	    </example>

	    <caution><para>A command run in the background within a
	      script may cause the script to hang, waiting
	      for a keystroke. Fortunately, there is a <link
	      linkend="waithang">remedy</link> for this.</para></caution>

	    </listitem>
	</varlistentry>

	<varlistentry><term><token>&&</token></term>
	  <indexterm>
	    <primary>&&</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>&&</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>and</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>logical operator</primary>
	  </indexterm>	  

	  <listitem>
	    <formalpara><title><link linkend="logops1">AND logical
	    operator</link></title>

	      <para>In a <link linkend="testconstructs1">test
		construct</link>, the <token>&&</token> operator causes
		a return of <returnvalue>0</returnvalue> (success) only if
		<emphasis>both</emphasis> the linked test conditions
		are true.</para>

	    </formalpara>

	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="dashref"><token>-</token></term>
	  <listitem><formalpara><title>option, prefix</title>
	      <para>Option flag for a command or filter. Prefix for
	        an operator.</para>
	    </formalpara>
	      <para><userinput>COMMAND -[Option1][Option2][...]</userinput></para>
	      <para><userinput>ls -al</userinput></para>
	      <para><userinput>sort -dfu $filename</userinput></para>
	      <para><userinput>set -- $variable</userinput></para>
	      <para>
	      <programlisting>if [ $file1 -ot $file2 ]
then
  echo "File $file1 is older than $file2."
fi

if [ "$a" -eq "$b" ]
then
  echo "$a is equal to $b."
fi

if [ "$c" -eq 24 -a "$d" -eq 47 ]
then
  echo "$c equals 24 and $d equals 47."
fi</programlisting>  
	      </para>
  
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>-</token></term>
	  <indexterm>
	    <primary>-</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>-</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>redirection</primary>
	    <secondary>from/to stdin/stdout</secondary>
	  </indexterm>	  
	  <listitem><formalpara><title>redirection from/to <filename>stdin</filename> or <filename>stdout</filename></title>
	    <para><anchor id="coxex">[dash]</para>
	    </formalpara>


	    <para><programlisting>(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
# Move entire file tree from one directory to another
# [courtesy Alan Cox &lt;a.cox@swansea.ac.uk&gt;, with a minor change]

# 1) cd /source/directory    Source directory, where the files to be moved are.
# 2) &&                     "And-list": if the 'cd' operation successful, then execute the next command.
# 3) tar cf - .              The 'c' option 'tar' archiving command creates a new archive,
#                            the 'f' (file) option, followed by '-' designates the target file as stdout,
#                            and do it in current directory tree ('.').
# 4) |                       Piped to...
# 5) ( ... )                 a subshell
# 6) cd /dest/directory      Change to the destination directory.
# 7) &&                     "And-list", as above
# 8) tar xpvf -              Unarchive ('x'), preserve ownership and file permissions ('p'),
#                            and send verbose messages to stdout ('v'),
#                            reading data from stdin ('f' followed by '-').
#
#                            Note that 'x' is a command, and 'p', 'v', 'f' are options.
# Whew!



# More elegant than, but equivalent to:
#   cd source-directory
#   tar cf - . | (cd ../target-directory; tar xzf -)
#
# cp -a /source/directory /dest     also has same effect.
</programlisting></para>

	    <para><programlisting>bunzip2 linux-2.4.3.tar.bz2 | tar xvf -
# --uncompress tar file--    | --then pass it to "tar"--
# If "tar" has not been patched to handle "bunzip2",
# this needs to be done in two discrete steps, using a pipe.
# The purpose of the exercise is to unarchive "bzipped" kernel source.
</programlisting></para>
       
          <para>Note that in this context the <quote>-</quote> is not
            itself a Bash operator, but rather an option recognized by
	    certain UNIX utilities that write to
	    <filename>stdout</filename>, such as <command>tar</command>,
	    <command>cat</command>, etc.</para>


	    <para>
	      <screen><prompt>bash$ </prompt><userinput>echo "whatever" | cat -</userinput>
<computeroutput>whatever</computeroutput> </screen>
	    </para>


	    <para>Where a filename is expected,
	      <replaceable>-</replaceable> redirects output to
	      <filename>stdout</filename> (sometimes seen with
	      <userinput>tar cf</userinput>), or accepts input from
	      <filename>stdin</filename>, rather than from a file. This
	      is a method of using a file-oriented utility as a filter
	      in a pipe.</para>

	    <para>
	      <screen><prompt>bash$ </prompt><userinput>file</userinput>
<computeroutput>Usage: file [-bciknvzL] [-f namefile] [-m magicfiles] file...</computeroutput>
	      </screen>

	    By itself on the command line, <link
	      linkend="fileref">file</link> fails with an error message.
	    </para>

	    <para>
	    Add a <quote>-</quote> for a more useful result. This causes the
	      shell to await user input.

	      <screen>
<prompt>bash$ </prompt><userinput>file -</userinput>
<userinput>abc</userinput>
<computeroutput>standard input:              ASCII text</computeroutput>



<prompt>bash$ </prompt><userinput>file -</userinput>
<userinput>#!/bin/bash</userinput>
<computeroutput>standard input:              Bourne-Again shell script text executable</computeroutput>
	      </screen>

	      Now the command accepts input from <filename>stdin</filename>
	        and analyzes it.
	    </para>

	    <para>The <quote>-</quote> can be used to pipe
	      <filename>stdout</filename> to other commands. This permits
	      such stunts as <link linkend="prependref">prepending lines
	      to a file</link>.</para>

	    <para>Using <link linkend="diffref">diff</link> to
	      compare a file with a <emphasis>section</emphasis>
	      of another:</para>

<para><userinput>grep Linux file1 | diff file2 -</userinput></para>	      


            <para>Finally, a real-world example using
	      <replaceable>-</replaceable> with <link
	      linkend="tarref">tar</link>.</para>

	    <example id="ex58">
	      <title>Backup of all files changed in last day</title>
	      <programlisting>&ex58;</programlisting>
	    </example>

	    <caution>

	    <para>Filenames beginning with
	      <quote>-</quote> may cause problems when coupled with the
	      <quote>-</quote> redirection operator. A script should
	      check for this and add an appropriate prefix to such
	      filenames, for example <filename>./-FILENAME</filename>,
	      <filename>$PWD/-FILENAME</filename>, or
	      <filename>$PATHNAME/-FILENAME</filename>.</para>

	      <para>If the value of a variable begins with a
	        <replaceable>-</replaceable>, this may likewise create
		problems.
		<programlisting>var="-n"
echo $var		
# Has the effect of "echo -n", and outputs nothing.</programlisting>
              </para>
	      </caution>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><token>-</token></term>
	  <listitem><formalpara><title>previous working directory</title>
	      <para>[dash]  <command>cd -</command> changes to the
		previous working directory. This uses the
		<link linkend="oldpwd">$OLDPWD</link> <link
		linkend="envref">environmental variable</link>.</para>
	    </formalpara>
	      <caution><para>Do not confuse the <quote>-</quote> used in this
		sense with the <quote>-</quote> redirection
		operator just discussed. The interpretation of the
		<quote>-</quote> depends on the context in which it
		appears.</para></caution>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>-</token></term>
	  <listitem><formalpara><title>Minus</title>
	      <para>Minus sign in an <link linkend="arops1">arithmetic
	        operation</link>.</para>
	    </formalpara>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>=</token></term>
	  <listitem><formalpara><title>Equals</title>
	      <para><link linkend="eqref">Assignment operator</link>
	        <programlisting>a=28
echo $a   # 28</programlisting></para>
	    </formalpara>
	    <para>In a <link linkend="equalsignref">different context</link>,
	      the <quote><token>=</token></quote> is a <link
	      linkend="scomparison1">string comparison</link>
	      operator.</para>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>+</token></term>
	  <listitem><formalpara><title>Plus</title>
	      <para>Addition  <link linkend="arops1">arithmetic
	        operator</link>.</para>
	    </formalpara>
	    <para>In a <link linkend="plusref">different context</link>,
	      the <token>+</token> is a <link linkend="regexp">Regular
	      Expression</link> operator.</para>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>+</token></term>
	  <listitem><formalpara><title>Option</title>
	      <para>Option flag for a command or filter.</para>
	    </formalpara>
	    <para>Certain commands and <link
	      linkend="builtinref">builtins</link> use the
	      <token>+</token> to enable certain options and the
	      <token>-</token> to disable them.</para>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>%</token></term>
	  <listitem><formalpara><title><link linkend="moduloref">modulo</link></title>
	      <para>Modulo (remainder of a division) <link linkend="arops1">arithmetic
	        operation</link>.</para>
	    </formalpara>
	    <para>In a <link linkend="pctpatref">different context</link>,
	      the <token>%</token> is a <link linkend="psub2">pattern
	      matching</link> operator.</para>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>~</token></term>
	  <listitem><formalpara><title>home directory</title>

	      <para>[tilde]  This corresponds to the <link
	        linkend="homedirref">$HOME</link> internal variable.

	      <emphasis>~bozo</emphasis> is bozo's home directory,
		and <command>ls ~bozo</command> lists the contents of it.
		<token>~/</token> is the current user's home directory,
		and <command>ls ~/</command> lists the contents of it.

	      <screen><prompt>bash$ </prompt><userinput>echo ~bozo</userinput>
<computeroutput>/home/bozo</computeroutput>

<prompt>bash$ </prompt><userinput>echo ~</userinput>
<computeroutput>/home/bozo</computeroutput>

<prompt>bash$ </prompt><userinput>echo ~/</userinput>
<computeroutput>/home/bozo/</computeroutput>

<prompt>bash$ </prompt><userinput>echo ~:</userinput>
<computeroutput>/home/bozo:</computeroutput>

<prompt>bash$ </prompt><userinput>echo ~nonexistent-user</userinput>
<computeroutput>~nonexistent-user</computeroutput>
	      </screen>
	      </para>

	    </formalpara>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>~+</token></term>
	  <listitem><formalpara><title>current working directory</title>
	      <para>This corresponds to the <link
	        linkend="pwdref">$PWD</link> internal variable.</para>
	    </formalpara>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>~-</token></term>
	  <listitem><formalpara><title>previous working directory</title>
	      <para>This corresponds to the <link
	        linkend="oldpwd">$OLDPWD</link> internal variable.</para>
	    </formalpara>
	    </listitem>
	</varlistentry>

	<varlistentry><term><token>^</token></term>
	  <indexterm>
	    <primary>^</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>^</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>regular expression</primary>
	  </indexterm>	  
	  <indexterm>
	    <primary>beginning of line</primary>
	  </indexterm>	  

	  <listitem>
	    <formalpara><title>beginning-of-line</title>
	      <para>In a <link linkend="regexref">regular expression</link>, a
	        <quote>^</quote> addresses the beginning of a line of text.</para>
	    </formalpara>

	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Control Characters</term>
	  <listitem>
	  <para><anchor id="controlcharref"></para>
	  <formalpara><title> change the behavior of the
	        terminal or text display.</title>
	    <para>A control character is a <keycap>CONTROL</keycap>
	      + <keycap>key</keycap> combination.</para>
	    </formalpara>

	    <itemizedlist id="ctlchar">

	      <listitem>
	        <para><userinput>Ctl-C</userinput></para>
		<para>Terminate a foreground job.</para>
	      </listitem>

	      <listitem>
	        <para><anchor id="ctldref"></para>
	        <para><userinput>Ctl-D</userinput></para>
		<para>Log out from a shell (similar to
		  <link linkend="exitcommandref">exit</link>).</para>
		<para><quote>EOF</quote> (end of file). This also
		  terminates input from <filename>stdin</filename>.</para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-G</userinput></para>
		<para><quote>BEL</quote> (beep).</para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-H</userinput></para>
		<para>Backspace.</para>
		<para>
		<programlisting>#!/bin/bash
# Embedding Ctl-H in a string.

a="^H^H"                  # Two Ctl-H's (backspaces).
echo "abcdef"             # abcdef
echo -n "abcdef$a "       # abcd f
#  Space at end  ^              ^ Backspaces twice.
echo -n "abcdef$a"        # abcdef
#  No space at end                Doesn't backspace (why?).
                          # Results may not be quite as expected.
echo; echo</programlisting>
                </para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-J</userinput></para>
		<para>Carriage return.</para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-L</userinput></para>
		<para>Formfeed (clear the terminal screen). This has
		  the same effect as the <link
		  linkend="clearref">clear</link> command.</para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-M</userinput></para>
		<para>Newline.</para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-U</userinput></para>
		<para>Erase a line of input.</para>
	      </listitem>

	      <listitem>
	        <para><userinput>Ctl-Z</userinput></para>
		<para>Pause a foreground job.</para>
	      </listitem>

	    </itemizedlist>



	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Whitespace</term>
	  <listitem>
	  <para><anchor id="whitespaceref"></para>
	  <formalpara><title>functions as a separator, separating commands or variables.</title>
	      <para>Whitespace consists of either spaces, tabs, blank
		lines, or any combination thereof. In some contexts,
		such as <link linkend="wsbad">variable assignment</link>,
		whitespace is not permitted, and results in a syntax
		error.</para>
	    </formalpara>

	  <para>Blank lines have no effect on the action of a script,
	    and are therefore useful for visually separating functional
	    sections.</para>

	  <para><link linkend="ifsref">$IFS</link>, the special variable
	    separating fields of input to certain commands, defaults
	    to whitespace.</para>

	  </listitem>
	</varlistentry>


      </variablelist>

  </chapter> <!-- Special characters used in shell scripts -->



  <chapter id="variables">
      <title>Introduction to Variables and Parameters</title>

      <para>Variables are at the heart of every programming and scripting
        language. They appear in arithmetic operations and manipulation
        of quantities, string parsing, and are indispensable for working
        in the abstract with symbols - tokens that represent something
        else. A variable is nothing more than a location or set of
        locations in computer memory holding an item of data.</para>

     <sect1 id="varsubn">
        <title>Variable Substitution</title>

      <para>The <emphasis>name</emphasis> of a variable is a placeholder for
        its <emphasis>value</emphasis>, the data it holds. Referencing its
	value is called <emphasis>variable substitution</emphasis>.</para>

      <variablelist id="dollarsign">

	<varlistentry>
	  <term><token>$</token></term> <indexterm>
	    <primary>$</primary>
	  </indexterm> <indexterm>
	    <primary>variable</primary> <secondary>$</secondary>
	  </indexterm> <indexterm>
	    <primary>variable</primary>
	    <secondary>substitution</secondary>
	  </indexterm>

	  <listitem>

	      <para>Let us carefully distinguish between the
		<emphasis>name</emphasis> of a variable
		and its <emphasis>value</emphasis>. If
		<userinput>variable1</userinput> is the name of a
		variable, then <userinput>$variable1</userinput>
		is a reference to its <emphasis>value</emphasis>,
		the data item it contains. The only time a
		variable appears <quote>naked</quote>, without
		the <token>$</token> prefix, is when declared
		or assigned, when <emphasis>unset</emphasis>,
		when <link linkend="exportref">exported</link>,
		or in the special case of a variable representing
		a <link linkend="signald">signal</link> (see
		<xref linkend="ex76">). Assignment may be with an
		<token>=</token> (as in <emphasis>var1=27</emphasis>),
		in a <link linkend="readref">read</link> statement,
		and at the head of a loop (<emphasis>for var2 in 1 2
		3</emphasis>).</para>


	    <para><anchor id="dblquo">Enclosing a referenced value in
	      double quotes (<token>" "</token>) does not
	      interfere with variable substitution. This is called
	      partial quoting, sometimes referred to as <quote>weak
	      quoting</quote>. <anchor id="snglquo">Using single quotes
	      (<token>' '</token>) causes the variable name to be used
	      literally, and no substitution will take place. This is
	      full quoting, sometimes referred to as <quote>strong
	      quoting</quote>. See <xref linkend="quoting"> for a
	      detailed discussion.</para>

	    <para>Note that <userinput>$variable</userinput> is actually a
	      simplified alternate form of
	      <userinput>${variable}</userinput>.  In contexts
	      where the <userinput>$variable</userinput> syntax
	      causes an error, the longer form may work (see <xref
	      linkend="Parameter-Substitution">, below).</para>

	    <example id="ex9">
	      <title>Variable assignment and substitution</title>
	      <programlisting>&ex9;</programlisting>
	    </example>

	    <caution>

	    <para>An uninitialized variable has a
	      <quote>null</quote> value - no assigned value at all
	      (not zero!).  Using a variable before assigning a value
	      to it will usually cause problems.</para>

	    <para>It is nevertheless possible to perform arithmetic operations
	      on an uninitialized variable.

	        <programlisting>echo "$uninitialized"                                # (blank line)
let "uninitialized += 5"                             # Add 5 to it.
echo "$uninitialized"                                # 5

#  Conclusion:
#  An uninitialized variable has no value, however
#+ it acts as if it were 0 in an arithmetic operation.
#  This is undocumented (and probably non-portable) behavior.</programlisting>

              See also <xref linkend="selfsource">.</para>

	      </caution>

	  </listitem>
	</varlistentry>
      </variablelist>
    </sect1> <!-- Variable Substitution -->  


    <sect1 id="varassignment">
      <title>Variable Assignment</title>

      <variablelist>
	<varlistentry>
	  <term><anchor id="eqref"><token>=</token></term>
	  <indexterm>
	    <primary>=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>assignment</secondary>
	  </indexterm>
	  <listitem><para>the assignment operator (<emphasis>no space before &
		after</emphasis>)</para>


	    <caution>
	    <para>Do not confuse this with <link
	      linkend="equalsignref">=</link> and <link
	      linkend="equalref">-eq</link>, which test, rather than
	      assign!</para>

	    <para>Note that <token>=</token> can be either an assignment
	      or a test operator, depending on context.</para>
	    </caution>


	<example id="ex15">
	  <title>Plain Variable Assignment</title>
	  <programlisting>&ex15;</programlisting>
	</example>

	<example id="ex16">
	  <title>Variable Assignment, plain and fancy</title>
	  <programlisting>&ex16;</programlisting>
	</example>

	    <para>Variable assignment using the <token>$(...)</token> mechanism
	      (a newer method than <link
	      linkend="backquotesref">backquotes</link>)</para>

	    <para><programlisting># From /etc/rc.d/rc.local
R=$(cat /etc/redhat-release)
arch=$(uname -m)</programlisting></para>
	  </listitem>
	</varlistentry>
      </variablelist>

    </sect1> <!-- Variable Assignment -->

    <sect1 id="untyped">
      <title>Bash Variables Are Untyped</title>
      
      <para><anchor id="bvuntyped"></para>
      <para>Unlike many other programming languages, Bash does not segregate
	its variables by <quote>type</quote>. Essentially, Bash
	variables are character strings, but, depending on context, Bash
	permits integer operations and comparisons on variables. The
	determining factor is whether the value of a variable contains
	only digits.</para>

	    <example id="intorstring">
	      <title>Integer or string?</title>
	      <programlisting>&intorstring;</programlisting>
	    </example>	    

      <para>Untyped variables are both a blessing and a curse. They permit
	more flexibility in scripting (enough rope to hang yourself!) and
	make it easier to grind out lines of code. However, they permit
	errors to creep in and encourage sloppy programming habits.</para>

      <para>The burden is on the programmer to keep track of what type the
        script variables are. Bash will not do it for you.</para>
    
    </sect1> <!-- Bash Variables Are Untyped-->


    <sect1 id="othertypesv">
      <title>Special Variable Types</title>

      <variablelist>

	<varlistentry>
	  <term><replaceable>local variables</replaceable></term>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>local</secondary>
	  </indexterm>

	  <listitem><para>variables visible only within a <link
	      linkend="codeblockref">code block</link> or function
	      (see also <link linkend="localref">local variables</link>
	      in <link linkend="functionref">functions</link>)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="envref"><replaceable>environmental variables</replaceable></term>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>environmental</secondary>
	  </indexterm>
	  <listitem>

	  <para>variables that affect the behavior of the shell and
	      user interface</para>

	      <note>

	      <para>In a more general context, each process has an
		<quote>environment</quote>, that is, a group of
		variables that hold information that the process
		may reference. In this sense, the shell behaves like
		any other process.</para>

	      <para>Every time a shell starts, it creates shell variables that
		correspond to its own environmental variables. Updating
		or adding new environmental variables causes the shell
		to update its environment, and all the shell's child
		processes (the commands it executes) inherit this
		environment.</para>

	      </note>

	      <caution>
	      <para>The space allotted to the environment is limited.
	        Creating too many environmental variables or ones that use up
		excessive space may cause problems.</para>
	      <para>
	          <screen>
<prompt>bash$ </prompt><userinput>eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ/'`"</userinput>

<prompt>bash$ </prompt><userinput>du</userinput>
<computeroutput>bash: /usr/bin/du: Argument list too long</computeroutput>
	          </screen>
	      </para>
	      <para>(Thank you, S. C. for the clarification, and
		for providing the above example.)</para>
	      </caution>

	    <para>If a script sets environmental variables, they need to be
	      <quote>exported</quote>, that is, reported to the
	      environment local to the script. This is the function of
	      the <link linkend="exportref">export</link> command.</para>

            <anchor id="childref">
	    <note><para>A script can <command>export</command> variables only
	      to child processes, that is, only to commands or processes
	      which that particular script initiates. A script invoked
	      from the command line <replaceable>cannot</replaceable>
	      export variables back to the command line environment. <link
	      linkend="forkref">Child processes</link> cannot export
	      variables back to the parent processes that spawned
	      them.</para></note>

	      <para>---</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="posparamref1"><replaceable>positional parameters</replaceable></term>
	  <indexterm>
	    <primary>parameter</primary>
	    <secondary>positional</secondary>
	  </indexterm>
	  <listitem>
	    <para>arguments passed to the script from the command
	      line - $0, $1, $2, $3... $0 is the name of the script
	      itself, $1 is the first argument, $2 the second, $3 the
	      third, and so forth.

	      <footnote><para>The process calling the script sets the
	        <replaceable>$0</replaceable> parameter. By convention, this
		parameter is the name of the script. See the manpage for
		<command>execv</command>.</para></footnote>

	      <anchor id="bracketnotation">
	      After $9, the arguments must be enclosed in brackets,
	      for example, ${10}, ${11}, ${12}.</para>

	    <para>The special variables <link linkend="appref">$* and $@</link>
	      denote <emphasis>all</emphasis> the positional parameters.</para>

	    <example id="ex17">
	      <title>Positional Parameters</title>
	      <programlisting>&ex17;</programlisting>
	    </example>

	    <para>The <emphasis>bracket notation</emphasis> for positional
	      parameters leads to a fairly simple way of referencing
	      the <emphasis>last</emphasis> argument passed to a
	      script on the command line. This also requires <link
	      linkend="varrefnew">indirect referencing</link>.</para>

	    <para><programlisting>args=$#           # Number of args passed.
lastarg=${!args}  # Note that lastarg=${!$#} doesn't work.</programlisting></para>


	    <para>Some scripts can perform different operations,
	      depending on which name they are invoked with. For this
	      to work, the script needs to check <varname>$0</varname>,
	      the name it was invoked by. There must also exist symbolic
	      links to all the alternate names of the script.</para>

	    <tip><para>If a script expects a command line parameter
	      but is invoked without one, this may cause a null variable
	      assignment, generally an undesirable result. One way to prevent
	      this is to append an extra character to both sides of the
	      assignment statement using the expected positional parameter.
	      </para></tip>

	      <programlisting>variable1_=$1_
# This will prevent an error, even if positional parameter is absent.

critical_argument01=$variable1_

# The extra character can be stripped off later, if desired, like so.
variable1=${variable1_/_/}   # Side effects only if $variable1_ begins with "_".
# This uses one of the parameter substitution templates discussed in Chapter 9.
# Leaving out the replacement pattern results in a deletion.

#  A more straightforward way of dealing with this is
#+ to simply test whether expected positional parameters have been passed.
if [ -z $1 ]
then
  exit $POS_PARAMS_MISSING
fi  
</programlisting>

	      <para>---</para>

	    <example id="ex18">
	      <title><command>wh</command>, <link
	        linkend="whoisref">whois</link> domain name lookup</title>
	      <programlisting>&ex18;</programlisting>
	    </example>

	      <para>---</para>

	    <para><anchor id="shiftref"></para>
	    <para>
	      <indexterm>
		<primary>shift</primary>
	      </indexterm>
	      <indexterm>
		<primary>command</primary>
		<secondary>shift</secondary>
	      </indexterm>
	      The <command>shift</command> command reassigns the positional
	      parameters, in effect shifting them to the left one notch.</para>
	      
	    <para><varname>$1</varname> <--- <varname>$2</varname>, <varname>$2</varname> <--- <varname>$3</varname>, <varname>$3</varname> <--- <varname>$4</varname>, etc.</para>

	    <para>The old <varname>$1</varname> disappears, but
	      <emphasis><varname>$0</varname> (the script name)
	      does not change</emphasis>. If you use a large number of
	      positional parameters to a script, <command>shift</command>
	      lets you access those past <literal>10</literal>, although
	      <link linkend="bracketnotation">{bracket} notation</link>
	      also permits this.</para>

	    <example id="ex19">
	      <title>Using <command>shift</command></title>
	      <programlisting>&ex19;</programlisting>
	    </example>

          <note><para>The <command>shift</command> command also works on
	    parameters passed to a <link
	    linkend="functionref">function</link>.  See <xref
	    linkend="multiplication">.</para></note>
	    
	  </listitem>
	</varlistentry>
      </variablelist>

    </sect1> <!-- Special Variable Types -->  


  </chapter> <!-- Variables -->



  <chapter id="quoting">
    <title>Quoting</title>
    
      <para><anchor id="quotingref"></para>

      <indexterm>
	<primary>"</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>"</secondary>
      </indexterm>
      <indexterm>
	<primary>'</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>'</secondary>
      </indexterm>
      <indexterm>
	<primary>quote</primary>
      </indexterm>
      <indexterm>
	<primary>\</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>\</secondary>
      </indexterm>
      <indexterm>
	<primary>escape</primary>
      </indexterm>
      <para>Quoting means just that, bracketing a string in quotes. This
	has the effect of protecting special characters in the string from
	reinterpretation or expansion by the shell or shell script. (A character
	is <quote>special</quote> if it has an interpretation other than its
	literal meaning, such as the <token>wild card</token> character,
      <token>*</token>.)</para>

	      <para>
	      <screen><prompt>bash$ </prompt><userinput>ls -l [Vv]*</userinput>
<computeroutput>-rw-rw-r--    1 bozo  bozo       324 Apr  2 15:05 VIEWDATA.BAT
 -rw-rw-r--    1 bozo  bozo       507 May  4 14:25 vartrace.sh
 -rw-rw-r--    1 bozo  bozo       539 Apr 14 17:11 viewdata.sh
</computeroutput>

<prompt>bash$ </prompt><userinput>ls -l '[Vv]*'</userinput>
<computeroutput>ls: [Vv]*: No such file or directory</computeroutput></screen>	      
	      </para>


      <note>
      <para>Certain programs and utilities can still reinterpret or expand
	special characters in a quoted string. This is an important use
	of quoting, protecting a command-line parameter from the shell,
	but still letting the calling program expand it.</para>

              <para>
	      <screen><prompt>bash$ </prompt><userinput>grep '[Ff]irst' *.txt</userinput>
<computeroutput>file1.txt:This is the first line of file1.txt.
 file2.txt:This is the First line of file2.txt.</computeroutput></screen>
	      </para>

	<para>Note that the unquoted <userinput>grep [Ff]irst *.txt</userinput>
	  works under the Bash shell, but <emphasis>not</emphasis> under
	  <command>tcsh</command>.</para>
	</note>


      <para>When referencing a variable, it is generally advisable to
	enclose it in double quotes (<token>" "</token>). This
	preserves all special characters within the variable name,
	except <token>$</token>, <token>`</token> (backquote),
	and <token>\</token> (escape).

	    <footnote>

	    <para>Encapsulating <quote>!</quote> within double
	      quotes gives an error when used <emphasis>from the command
	      line</emphasis>. Apparently this is interpreted as a <link
	      linkend="histcommands">history command</link>. Within a script,
	      though, this problem does not occur.</para>

	    <para>Of more concern is the inconsistent behavior of
	    <quote>\</quote> within double quotes.

	      <screen>
<prompt>bash$ </prompt><userinput>echo hello\!</userinput>
<computeroutput>hello!</computeroutput>


<prompt>bash$ </prompt><userinput>echo "hello\!"</userinput>
<computeroutput>hello\!</computeroutput>




<prompt>bash$ </prompt><userinput>echo -e x\ty</userinput>
<computeroutput>xty</computeroutput>


<prompt>bash$ </prompt><userinput>echo -e "x\ty"</userinput>
<computeroutput>x       y</computeroutput>
	      </screen>

              (Thank you, Wayne Pollock, for pointing this out.)
            </para>
	      
	      </footnote>
	
	Keeping <token>$</token> as a special character within
	double quotes permits referencing a quoted variable
	(<replaceable>"$variable"</replaceable>), that is, replacing the
	variable with its value (see <xref linkend="ex9">, above).</para>

      <para>Use double quotes to prevent word splitting.
            <footnote><para><quote>Word splitting</quote>, in this context,
	      means dividing a character string into a number of separate and
	      discrete arguments.</para></footnote>
	An argument enclosed in double quotes presents
	itself as a single word, even if it contains <link
	linkend="whitespaceref">whitespace</link> separators.

	<programlisting>variable1="a variable containing five words"
COMMAND This is $variable1    # Executes COMMAND with 7 arguments:
# "This" "is" "a" "variable" "containing" "five" "words"

COMMAND "This is $variable1"  # Executes COMMAND with 1 argument:
# "This is a variable containing five words"


variable2=""    # Empty.

COMMAND $variable2 $variable2 $variable2        # Executes COMMAND with no arguments. 
COMMAND "$variable2" "$variable2" "$variable2"  # Executes COMMAND with 3 empty arguments. 
COMMAND "$variable2 $variable2 $variable2"      # Executes COMMAND with 1 argument (2 spaces). 

# Thanks, S.C.
</programlisting></para>


      <tip><para>Enclosing the arguments to an <command>echo</command>
	statement in double quotes is necessary only when word splitting
	is an issue.</para></tip>

	    <example id="weirdvars">
	      <title>Echoing Weird Variables</title>
	      <programlisting>&weirdvars;</programlisting>
	    </example>

      <para>Single quotes (<token>' '</token>) operate similarly to double
	quotes, but do not permit referencing variables, since
	the special meaning of <token>$</token> is turned off.
	Within single quotes, <emphasis>every</emphasis> special
	character except <token>'</token> gets interpreted literally.
	Consider single quotes (<quote>full quoting</quote>) to be a
	stricter method of quoting than double quotes (<quote>partial
	quoting</quote>).</para>

      <note><para>Since even the escape character (<token>\</token>)
	gets a literal interpretation within single quotes, trying to
	enclose a single quote within single quotes will not yield the
	expected result.
	<programlisting>echo "Why can't I write 's between single quotes"

echo

# The roundabout method.
echo 'Why can'\''t I write '"'"'s between single quotes'
#    |-------|  |----------|   |-----------------------|
# Three single-quoted strings, with escaped and quoted single quotes between.

# This example courtesy of Stephane Chazelas.</programlisting>
      </para></note>


      <para><anchor id="escp"><firstterm>Escaping</firstterm> is a method
	of quoting single characters. The <token>escape</token>
	(<token>\</token>) preceding a character tells the shell to
	interpret that character literally.</para>

      <caution><para>With certain commands and utilities, such as <link
	linkend="echoref">echo</link> and <link
	linkend="sedref">sed</link>, escaping a character may have the
	opposite effect - it can toggle on a special meaning for that
	character.</para></caution>

      <variablelist id="specialmeanings">
	<title><anchor id="spm">Special meanings of certain
	escaped characters</title>

	<varlistentry>
	<term>used with <command>echo</command> and
	<command>sed</command></term>
	<listitem><para></para></listitem>
	</varlistentry>

	<varlistentry><term><token>\n</token></term>
	  <indexterm>
	    <primary>\n</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\n</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>newline</primary>
	  </indexterm>
	  <listitem><para>means newline</para>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>\r</token></term>
	  <indexterm>
	    <primary>\r</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\r</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>carriage return</primary>
	  </indexterm>
	  <listitem><para>means return</para>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>\t</token></term>
	  <indexterm>
	    <primary>\t</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\t</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>tabulation</primary>
	  </indexterm>
	  <listitem><para>means tab</para>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>\v</token></term>
	  <indexterm>
	    <primary>\v</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\v</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>vertical tabulation</primary>
	  </indexterm>
	  <listitem><para> means vertical tab</para>
	  </listitem>
	</varlistentry>

	<varlistentry><term><token>\b</token></term>
	  <indexterm>
	    <primary>\b</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\b</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>backspace</primary>
	  </indexterm>
	<listitem><para>means backspace</para>
	</listitem>
	</varlistentry>

	<varlistentry><term><token>\a</token></term>
	  <indexterm>
	    <primary>\a</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\a</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>alert</primary>
	  </indexterm>
	  <indexterm>
	    <primary>beep</primary>
	  </indexterm>
	  <indexterm>
	    <primary>flash</primary>
	  </indexterm>
	<listitem><para>means <quote>alert</quote> (beep or flash)</para>
	</listitem>
	</varlistentry>

	<varlistentry><term><token>\0xx</token></term>
	  <indexterm>
	    <primary>\0xx</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\0xx</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>octal ASCII</primary>
	  </indexterm>
	  <listitem><para>translates to the octal ASCII
	      equivalent of <replaceable>0xx</replaceable></para>
	      
      <example id="escaped">
	<title>Escaped Characters</title>
	<programlisting>&escaped;</programlisting>
      </example>

            <para>See <xref linkend="ex77"> for another example of the
              <userinput>$'   '</userinput> string expansion
              construct.</para>

	</listitem>
	</varlistentry>

	<varlistentry><term><token>\"</token></term>
	  <indexterm>
	    <primary>\"</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\"</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>quote</primary>
	  </indexterm>
	<listitem><para> gives the quote its literal meaning</para>
	<para><programlisting>echo "Hello"                  # Hello
echo "\"Hello\", he said."    # "Hello", he said.</programlisting></para>
	</listitem>
	</varlistentry>

	<varlistentry><term><token>\$</token></term>
	  <indexterm>
	    <primary>\$</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\$</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>dollar</primary>
	  </indexterm>
	  <listitem><para>gives the dollar sign its literal meaning
	      (variable name following <token>\$</token> will not be
	      referenced)</para>
	    <para><programlisting>echo "\$variable01"  # results in $variable01</programlisting></para>
	  </listitem>
	  </varlistentry>

	<varlistentry><term><token>\\</token></term>
	  <indexterm>
	    <primary>\\</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\\</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>double backslash</primary>
	  </indexterm>
	  <listitem><para>gives the backslash its literal meaning</para>
	    <para><programlisting>echo "\\"  # Results in \

# Whereas . . .

echo "\"   # Invokes secondary prompt from the command line.
           # In a script, gives an error message.</programlisting></para>
	  </listitem>
	  </varlistentry>
	</variablelist>

      <note>
      <para>The behavior of <token>\</token> depends on whether
	it is itself escaped, quoted, or appearing within <link
	linkend="commandsubref">command substitution</link> or a <link
	linkend="heredocref">here document</link>.

	<programlisting>                      #  Simple escaping and quoting
echo \z               #  z
echo \\z              # \z
echo '\z'             # \z
echo '\\z'            # \\z
echo "\z"             # \z
echo "\\z"            # \z

                      #  Command substitution
echo `echo \z`        #  z
echo `echo \\z`       #  z
echo `echo \\\z`      # \z
echo `echo \\\\z`     # \z
echo `echo \\\\\\z`   # \z
echo `echo \\\\\\\z`  # \\z
echo `echo "\z"`      # \z
echo `echo "\\z"`     # \z

                      # Here document
cat &lt;&lt;EOF              
\z                      
EOF                   # \z

cat &lt;&lt;EOF              
\\z                     
EOF                   # \z

# These examples supplied by Stephane Chazelas.</programlisting>
      </para>

      <para>Elements of a string assigned to a variable may be escaped, but
        the escape character alone may not be assigned to a variable.
	<programlisting>variable=\
echo "$variable"
# Will not work - gives an error message:
# test.sh: : command not found
# A "naked" escape cannot safely be assigned to a variable.
#
#  What actually happens here is that the "\" escapes the newline and
#+ the effect is        variable=echo "$variable"
#+                      invalid variable assignment

variable=\
23skidoo
echo "$variable"        #  23skidoo
                        #  This works, since the second line
                        #+ is a valid variable assignment.

variable=\ 
#        \^    escape followed by space
echo "$variable"        # space

variable=\\
echo "$variable"        # \

variable=\\\
echo "$variable"
# Will not work - gives an error message:
# test.sh: \: command not found
#
#  First escape escapes second one, but the third one is left "naked",
#+ with same result as first instance, above.

variable=\\\\
echo "$variable"        # \\
                        # Second and fourth escapes escaped.
                        # This is o.k.</programlisting>
      </para>
      
      </note>   



      <para>Escaping a space can prevent word splitting in a command's argument list.
        <programlisting>file_list="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7"
# List of files as argument(s) to a command.

# Add two files to the list, and list all.
ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list

echo "-------------------------------------------------------------------------"

# What happens if we escape a couple of spaces?
ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list
# Error: the first three files concatenated into a single argument to 'ls -l'
#        because the two escaped spaces prevent argument (word) splitting.</programlisting>
</para>


      <para>The <token>escape</token> also provides a means of writing a
	multi-line command. Normally, each separate line constitutes
	a different command, but an <token>escape</token> at the end
	of a line <emphasis>escapes the newline character</emphasis>,
	and the command sequence continues on to the next line.</para>
      <para><programlisting>(cd /source/directory && tar cf - . ) | \
(cd /dest/directory && tar xpvf -)
# Repeating Alan Cox's directory tree copy command,
# but split into two lines for increased legibility.

# As an alternative:
tar cf - -C /source/directory . |
tar xpvf - -C /dest/directory
# See note below.
# (Thanks, Stephane Chazelas.)</programlisting>
        
	<note><para>If a script line ends with a <token>|</token>, a pipe
	  character, then a <token>\</token>, an escape, is not strictly
	  necessary. It is, however, good programming practice to always
	  escape the end of a line of code that continues to the
	  following line.</para></note></para>

	<para><programlisting>echo "foo
bar" 
#foo
#bar

echo

echo 'foo
bar'    # No difference yet.
#foo
#bar

echo

echo foo\
bar     # Newline escaped.
#foobar

echo

echo "foo\
bar"     # Same here, as \ still interpreted as escape within weak quotes.
#foobar

echo

echo 'foo\
bar'     # Escape character \ taken literally because of strong quoting.
#foo\
#bar

# Examples suggested by Stephane Chazelas.</programlisting></para>



  </chapter> <!-- Quoting -->


  <chapter id="exit-status">
    <title>Exit and Exit Status</title>

    <epigraph>
      <attribution>Chet Ramey</attribution>
      <para>...there are dark corners in the Bourne shell, and people use all
      of them.</para>
    </epigraph>
    
      <para><anchor id="exitcommandref">The 
	<command>
	  <indexterm>
	    <primary>exit</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>exit</secondary>
	  </indexterm>
	  exit
	</command> 
	command may be used to terminate a script, just as in a C program.
	It can also return a value, which is available to the script's parent
	process.</para>


      <para><anchor id="exitstatusref">Every command returns an 
	<firstterm>
	  <indexterm>
	    <primary>exit status</primary>
	  </indexterm>
	  exit status
	</firstterm> 
	(sometimes referred to as a 
	<firstterm>
	  <indexterm>
	    <primary>return status</primary>
	  </indexterm>
	  return status
	</firstterm>). A successful command returns a
	<returnvalue>0</returnvalue>, while an unsuccessful one returns
	a <returnvalue>non-zero</returnvalue> value that usually may
	be interpreted as an error code. Well-behaved UNIX commands,
	programs, and utilities return a <returnvalue>0</returnvalue>
	exit code upon successful completion, though there are some
	exceptions.</para>

      <para>Likewise, functions within a script and the script itself
	return an exit status. The last command executed in the function
	or script determines the exit status. Within a script, an
	<userinput>exit <replaceable>nnn</replaceable></userinput>
	command may be used to deliver an
	<returnvalue><replaceable>nnn</replaceable></returnvalue> exit status
	to the shell (<returnvalue><replaceable>nnn</replaceable></returnvalue>
	must be a decimal number in the <returnvalue>0</returnvalue> -
	<returnvalue>255</returnvalue> range).</para>

      <note><para>When a script ends with an <command>exit</command> that has
	no parameter, the exit status of the script is the exit status of
	the last command executed in the script (<emphasis>not</emphasis>
	counting the <command>exit</command>).</para></note>

      <para><anchor id="exsref"></para>

      <para>
	<varname>
	  <indexterm>
	    <primary>$?</primary>
	  </indexterm> <indexterm>
	    <primary>variable</primary> <secondary>$?</secondary>
	  </indexterm> $?</varname> reads the exit status of the last
	    command executed. After a function returns,
	    <varname>$?</varname> gives the exit status of the last
	    command executed in the function. This is Bash's way of
	    giving functions a <quote>return value</quote>. After a
	    script terminates, a <varname>$?</varname> from the command
	    line gives the exit status of the script, that is, the last
	    command executed in the script, which is, by convention,
	    <userinput>0</userinput> on success or an integer in the
	    range 1 - 255 on error.</para>

      <example id="ex5">
	<title>exit / exit status</title>
	<programlisting>&ex5;</programlisting>
      </example>
      
      <para><link linkend="xstatvarref">$?</link> is especially useful
        for testing the result of a command in a script (see <xref
        linkend="filecomp"> and <xref linkend="lookup">).</para>

      <note>
      <para>The <link linkend="notref">!</link>, the logical
	<quote>not</quote> qualifier, reverses the outcome of a test or
	command, and this affects its <link linkend="exitstatusref">exit
	status</link>.

	<example id="negcond">
	<title>Negating a condition using <token>!</token></title>
	<programlisting>true  # the "true" builtin.
echo "exit status of \"true\" = $?"     # 0

! true
echo "exit status of \"! true\" = $?"   # 1
# Note that the "!" needs a space.
#    !true   leads to a "command not found" error

# Thanks, S.C.</programlisting>
        </example>

      </para>
      </note>


      <caution><para>Certain exit status codes have <link
	linkend="exitcodesref">reserved meanings</link> and should not
	be user-specified in a script.	</para></caution>


  </chapter> <!-- Exit and Exit status -->


  <chapter id="tests">
    <title>Tests</title>

      <para><anchor id="ifthen"></para>

      <indexterm>
	<primary>if</primary>
      </indexterm>
      <indexterm>
	<primary>test</primary>
	<secondary>if</secondary>
      </indexterm>
      <indexterm>
	<primary>then</primary>
      </indexterm>
      <indexterm>
	<primary>else if</primary>
      </indexterm>
      <indexterm>
	<primary>elif</primary>
      </indexterm>

        <para>Every reasonably complete programming language can test
	  for a condition, then act according to the result of
	  the test. Bash has the <command>test</command> command,
	  various bracket and parenthesis operators, and the
	  <command>if/then</command> construct.</para>

      <sect1 id="testconstructs">
	<title>Test Constructs</title>

	<para><anchor id="testconstructs1"></para>

      <itemizedlist id="testingref">

        <listitem>
	<para>An <command>if/then</command> construct tests whether the
	  <link linkend="exitstatusref">exit status</link> of a list
	  of commands is <returnvalue>0</returnvalue> (since 0 means
	  <quote>success</quote> by UNIX convention), and if so, executes
	  one or more commands.</para>
	</listitem>

        <listitem>
	<para>There exists a dedicated command called <command>
	[</command> (<link linkend="leftbracket">left bracket</link>
	special character). It is a synonym for <command>test</command>,
	and a <link linkend="builtinref">builtin</link> for efficiency
	reasons. This command considers its arguments as comparison
	expressions or file tests and returns an exit status corresponding
	to the result of the comparison (0 for true, 1 for false).</para>
	</listitem>

        <listitem>
	<para>With version 2.02, Bash introduced the <link
	  linkend="dblbrackets">[[ ... ]]</link> <emphasis>extended
	  test command</emphasis>, which performs comparisons
	  in a manner more familiar to programmers from other
	  languages. Note that <command>[[</command> is a <link
	  linkend="keywordref">keyword</link>, not a command.</para>

	<para>Bash sees <userinput>[[ $a -lt $b ]]</userinput> as a
	  single element, which returns an exit status.</para>

	<para>The <link linkend="dblparens">(( ... ))</link> and <link
	  linkend="letref">let ...</link> constructs also return an
	  exit status of <returnvalue>0</returnvalue> if the arithmetic
	  expressions they evaluate expand to a non-zero value. These
	  <link linkend="arithexpref">arithmetic expansion</link>
	  constructs may therefore be used to perform arithmetic
	  comparisons.

	    <programlisting>let "1&lt;2" returns 0 (as "1&lt;2" expands to "1")
(( 0 && 1 )) returns 1 (as "0 && 1" expands to "0")</programlisting>	    
	  </para>
        </listitem>

        <listitem>
	  <para>An <command>if</command> can test any command, not just
	    conditions enclosed within brackets.
	      <programlisting>if cmp a b &amp;&gt; /dev/null  # Suppress output.
then echo "Files a and b are identical."
else echo "Files a and b differ."
fi

if grep -q Bash file
then echo "File contains at least one occurrence of Bash."
fi

if COMMAND_WHOSE_EXIT_STATUS_IS_0_UNLESS_ERROR_OCCURRED
then echo "Command succeeded."
else echo "Command failed."
fi</programlisting>
          </para>
        </listitem>

        <listitem>

	  <para>An <command>if/then</command> construct can contain nested
	    comparisons and tests.
	      <programlisting>if echo "Next *if* is part of the comparison for the first *if*."

  if [[ $comparison = "integer" ]]
    then (( a < b ))
  else
    [[ $a < $b ]]
  fi

then
  echo '$a is less than $b'
fi</programlisting>
          </para> 

	  <para><emphasis>This detailed <quote>if-test</quote> explanation
	  courtesy of Stephane Chazelas.</emphasis></para>

        </listitem>


      </itemizedlist>



      <example id="ex10">
	<title>What is truth?</title>
	<programlisting>&ex10;</programlisting>
      </example>

      <formalpara><title>Exercise</title>
	<para>Explain the behavior of <xref linkend="ex10">, above.</para>
      </formalpara>
      
      <para><programlisting>if [ condition-true ]
then
   command 1
   command 2
   ...
else
   # Optional (may be left out if not needed).
   # Adds default code block executing if original condition tests false.
   command 3
   command 4
   ...
fi</programlisting>
      </para>

      <note>
      <para>When <emphasis>if</emphasis> and <emphasis>then</emphasis>
	are on same line in a condition test, a semicolon must
	terminate the <emphasis>if</emphasis> statement.  Both
	<emphasis>if</emphasis> and <emphasis>then</emphasis> are <link
	linkend="keywordref">keywords</link>.  Keywords (or commands)
	begin statements, and before a new statement on the same line
	begins, the old one must terminate.</para>

      <para><programlisting>if [ -x "$filename" ]; then</programlisting></para>
      </note>

      <variablelist id="elifref">
        <title><anchor id="elifref1">Else if and elif</title>
	<varlistentry>
          <term><token>elif</token></term>
	  <listitem>
	    <para><userinput>elif</userinput> is a contraction
	      for <token>else if</token>.  The effect is to nest an
	      inner <token>if/then</token> construct within an outer
	      one.</para>

	    <para><programlisting>if [ condition1 ]
then
   command1
   command2
   command3
elif [ condition2 ]
# Same as else if
then
   command4
   command5
else
   default-command
fi</programlisting>
	      </para>
	  </listitem>
	</varlistentry>
      </variablelist>

      <para>
      <indexterm>
	<primary>test</primary>
      </indexterm>
      <indexterm>
	<primary>test</primary>
	<secondary>test</secondary>
      </indexterm>
      <indexterm>
	<primary>[</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>[</secondary>
      </indexterm>
      <indexterm>
	<primary>]</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>]</secondary>
      </indexterm>
	
	The <userinput>if test condition-true</userinput> construct is the
	exact equivalent of <userinput>if [ condition-true ]</userinput>.
	As it happens, the left bracket, <command>[</command> , is a token
	which invokes the <command>test</command> command.  The closing
	right bracket, <command>]</command> , in an if/test should not
	therefore be strictly necessary, however newer versions of Bash
	require it.</para>

	<note><para>The <command>test</command> command is a Bash <link
	  linkend="builtinref">builtin</link> which tests file
	  types and compares strings. Therefore, in a Bash script,
	  <command>test</command> does <emphasis>not</emphasis> call
	  the external <filename>/usr/bin/test</filename> binary,
	  which is part of the <emphasis>sh-utils</emphasis>
	  package. Likewise, <token>[</token> does not call
	  <filename>/usr/bin/[</filename>, which is linked to
	  <filename>/usr/bin/test</filename>.</para>

	    <para>
	      <screen>
<prompt>bash$ </prompt><userinput>type test</userinput>
<computeroutput>test is a shell builtin</computeroutput>
<prompt>bash$ </prompt><userinput>type '['</userinput>
<computeroutput>[ is a shell builtin</computeroutput>
<prompt>bash$ </prompt><userinput>type '[['</userinput>
<computeroutput>[[ is a shell keyword</computeroutput>
<prompt>bash$ </prompt><userinput>type ']]'</userinput>
<computeroutput>]] is a shell keyword</computeroutput>
<prompt>bash$ </prompt><userinput>type ']'</userinput>
<computeroutput>bash: type: ]: not found</computeroutput>
	      </screen>
	    </para></note>
      

      <example id="ex11">
	<title>Equivalence of <token>test</token>,
	  <filename>/usr/bin/test</filename>, <token>[ ]</token>,
	  and <filename>/usr/bin/[</filename></title>
	<programlisting>&ex11;</programlisting>
      </example>


      <indexterm>
	<primary>test</primary>
      </indexterm>
      <indexterm>
	<primary>test</primary>
	<secondary>test</secondary>
      </indexterm>
      <indexterm>
	<primary>[[</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>[[</secondary>
      </indexterm>
      <indexterm>
	<primary>]]</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>]]</secondary>
      </indexterm>

      <para><anchor id="dblbrackets">The <token>[[  ]]</token> construct
	is the more versatile Bash version of <token>[	]</token>. This
	is the <emphasis>extended test command</emphasis>, adopted from
	<emphasis>ksh88</emphasis>.</para>

      <note><para>No filename expansion or word splitting takes place
	between <token>[[</token> and <token>]]</token>, but there is
	parameter expansion and command substitution.</para></note>

      <para>
	<programlisting>file=/etc/passwd

if [[ -e $file ]]
then
  echo "Password file exists."
fi</programlisting>
      </para>

      <tip>
      <para>Using the <command>[[ ... ]]</command> test construct,
	rather than <command>[ ... ]</command> can prevent many
	logic errors in scripts. For example, the <token>&&</token>,
	<token>||</token>, <token>&lt;</token>, and <token>&gt;</token>
	operators work within a <token>[[  ]]</token> test, despite
	giving an error within a <token>[  ]</token> construct.</para>
      </tip>

      <note>
      <para>Following an <command>if</command>, neither the
        <command>test</command> command nor the test brackets ( [ ] or [[ ]] )
	are strictly necessary.

	<programlisting>dir=/home/bozo

if cd "$dir" 2&gt;/dev/null; then   # "2&gt;/dev/null" hides error message.
  echo "Now in $dir."
else
  echo "Can't change to $dir."
fi</programlisting>

        The "if COMMAND" construct returns the exit status of COMMAND.
</para>

	
	<para>Similarly, a condition within test brackets may stand alone
	  without an <command>if</command>, when used in combination
	  with a <link linkend="listconsref">list construct</link>.

	  <programlisting>var1=20
var2=22
[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"

home=/home/bozo
[ -d "$home" ] || echo "$home directory does not exist."</programlisting></para>
	  </note>


      <indexterm>
	<primary>test</primary>
      </indexterm>
      <indexterm>
	<primary>test</primary>
	<secondary>test</secondary>
      </indexterm>
      <indexterm>
	<primary>((</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>))</secondary>
      </indexterm>
      <indexterm>
	<primary>((</primary>
      </indexterm>
      <indexterm>
	<primary>special character</primary>
	<secondary>))</secondary>
      </indexterm>

      <para>The <link linkend="dblparens">(( )) construct</link> expands
	and evaluates an arithmetic expression. If
	the expression evaluates as zero, it returns an
	<link linkend="exitstatusref">exit status</link> of
	<returnvalue>1</returnvalue>, or <quote>false</quote>. A non-zero
	expression returns an exit status of <returnvalue>0</returnvalue>,
	or <quote>true</quote>. This is in marked contrast to using
	the <command>test</command> and <token>[ ]</token> constructs
	previously discussed.</para>

        <example id="arithtests">
	  <title>Arithmetic Tests using <token>(( ))</token></title>
	  <programlisting>&arithtests;</programlisting>
        </example>

      </sect1> <!-- Test Constructs -->


      <sect1 id="fto">
	<title>File test operators</title>

	<variablelist>
	  <title><anchor id="rtif">Returns true if...</title>
	  <varlistentry>
	    <term><token>-e</token></term>
	    <listitem><para>file exists</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-f</token></term>
	    <listitem><para>file is a <replaceable>regular</replaceable>
	      file (not a directory or device file)</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-s</token></term>
	    <listitem><para>file is not zero size</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-d</token></term>
	    <listitem><para>file is a directory</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-b</token></term>
	    <listitem><para>file is a block device (floppy, cdrom, etc.)
	    </para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-c</token></term>
	    <listitem><para>file is a character device (keyboard, modem, sound
	    card, etc.)</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-p</token></term>
	    <listitem><para>file is a pipe</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-h</token></term>
	    <listitem><para>file is a symbolic link</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-L</token></term>
	    <listitem><para>file is a symbolic link</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-S</token></term>
	    <listitem><para>file is a socket</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-t</token></term>
	    <listitem>
	    <para>file (<link linkend="fdref">descriptor</link>) is
	      associated with a terminal device</para>
	    <para>This test option may be used to check whether the
	      <filename>stdin</filename> (<userinput>[ -t 0 ]</userinput>)
	      or <filename>stdout</filename> (<userinput>[ -t 1 ]</userinput>)
	      in a given script is a terminal.</para>
	    </listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-r</token></term>
	    <listitem><para>file has read permission (<emphasis>for the
	      user running the test</emphasis>)</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-w</token></term>
	    <listitem><para>file has write permission (for the user running
	      the test)</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-x</token></term>
	    <listitem><para>file has execute permission (for the user running
	    the test)</para></listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-g</token></term>
	    <listitem>
	    <para>set-group-id (sgid) flag set on file or directory</para>
	    <para>If a directory has the <replaceable>sgid</replaceable>
	      flag set, then a file created within that directory belongs
	      to the group that owns the directory, not necessarily to
	      the group of the user who created the file. This may be
	      useful for a directory shared by a workgroup.</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-u</token></term>
	    <listitem>
	    <para>set-user-id (suid) flag set on file</para>
	    <para>A binary owned by <emphasis>root</emphasis>
	      with <replaceable>set-user-id</replaceable> flag set
	      runs with <emphasis>root</emphasis> privileges, even
	      when an ordinary user invokes it.
	      
		<footnote><para>Be aware that <emphasis>suid</emphasis>
		  binaries may open security holes and that the
		  <emphasis>suid</emphasis> flag has no effect on
		  shell scripts.</para></footnote>

	      This is useful for executables (such as
	      <command>pppd</command> and <command>cdrecord</command>)
	      that need to access system hardware. Lacking the
	      <emphasis>suid</emphasis> flag, these binaries could not
	      be invoked by a non-root user.

	      <screen>
	      <computeroutput>-rwsr-xr-t    1 root       178236 Oct  2  2000 /usr/sbin/pppd</computeroutput>
	      </screen>

	      A file with the <replaceable>suid</replaceable> flag set shows
	      an <emphasis>s</emphasis> in its permissions.</para>

	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-k</token></term>
	    <listitem>

	    <para><replaceable>sticky bit</replaceable> set</para>

	    <para>Commonly known as the <quote>sticky bit</quote>, the
	      <emphasis>save-text-mode</emphasis> flag is a special
	      type of file permission. If a file has this flag set,
	      that file will be kept in cache memory, for quicker access.
	        <footnote><para>On modern UNIX systems, the sticky
		  bit is no longer used for files, only on
		  directories.</para></footnote>
	      If set on a directory, it restricts write permission.
	      Setting the sticky bit adds a <emphasis>t</emphasis>
	      to the permissions on the file or directory listing.

	      <screen>
	      <computeroutput>drwxrwxrwt    7 root         1024 May 19 21:26 tmp/</computeroutput>
	      </screen>
	    
	      If a user does not own a directory that has the sticky
	      bit set, but has write permission in that directory,
	      he can only delete files in it that he owns. This keeps
	      users from inadvertently overwriting or deleting each
	      other's files in a publicly accessible directory, such
	      as <filename class="directory">/tmp</filename>.</para>

	    </listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-O</token></term>
	    <listitem><para>you are owner of file</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-G</token></term>
	    <listitem><para>group-id of file same as yours</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-N</token></term>
	    <listitem><para>file modified since it was last read</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>f1 -nt f2</token></term>
	    <listitem><para>file <replaceable>f1</replaceable> is newer than
		<replaceable>f2</replaceable></para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>f1 -ot f2</token></term>
	    <listitem><para>file <replaceable>f1</replaceable> is older than
		<replaceable>f2</replaceable></para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>f1 -ef f2</token></term>
	    <listitem><para>files <replaceable>f1</replaceable> and
		<replaceable>f2</replaceable> are hard links to the same
		file</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>!</token></term>
	    <listitem><para><quote>not</quote> -- reverses the sense of the
	    tests above (returns true if condition absent).</para></listitem>
	  </varlistentry>
	</variablelist>

	<example id="brokenlink">
	  <title>Testing for broken links</title>
	  <programlisting>&brokenlink;</programlisting>
	</example>

	<para><xref linkend="cookies">, <xref linkend="bingrep">,
	  <xref linkend="fileinfo">, <xref linkend="ramdisk">, and <xref
	  linkend="mailformat"> also illustrate uses of the file test
	  operators.</para>


      </sect1> <!-- File test operators -->

      <sect1 id="comparison-ops">
	<title>Comparison operators (binary)</title>

	<variablelist id="icomparison">
	  <title><anchor id="icomparison1">integer comparison</title>

	  <varlistentry>
	    <term><token>-eq</token></term>
	    <listitem>
	    <para><anchor id="equalref"></para>
	    <para>is equal to</para>
	    <para><userinput>if [ "$a" -eq "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-ne</token></term>
	    <listitem>
	    <para>is not equal to</para>
	    <para><userinput>if [ "$a" -ne "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-gt</token></term>
	    <listitem>
	    <para>is greater than</para>
	    <para><userinput>if [ "$a" -gt "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-ge</token></term>
	    <listitem>
	    <para>is greater than or equal to</para>
	    <para><userinput>if [ "$a" -ge "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-lt</token></term>
	    <listitem>
	    <para>is less than</para>
	    <para><userinput>if [ "$a" -lt "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-le</token></term>
	    <listitem>
	    <para>is less than or equal to</para>
	    <para><userinput>if [ "$a" -le "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><anchor id="intlt"><token>&lt;</token></term>
	    <listitem>
	    <para>is less than (within <link linkend="dblparens">double
	      parentheses</link>)</para>
	    <para><userinput>(("$a" &lt; "$b"))</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>&lt;=</token></term>
	    <listitem>
	    <para>is less than or equal to (within double parentheses)</para>
	    <para><userinput>(("$a" &lt;= "$b"))</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>&gt;</token></term>
	    <listitem>
	    <para>is greater than (within double parentheses)</para>
	    <para><userinput>(("$a" &gt; "$b"))</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>&gt;=</token></term>
	    <listitem>
	    <para>is greater than or equal to (within double parentheses)</para>
	    <para><userinput>(("$a" &gt;= "$b"))</userinput></para>
	    </listitem>
	  </varlistentry>
	  
	</variablelist>
	
	<variablelist id="scomparison">
	  <title><anchor id="scomparison1">string comparison</title>
	  <varlistentry>
	    <term><token>=</token></term>
	    <listitem>
	    <para><anchor id="equalsignref"></para>
	    <para>is equal to</para>
	    <para><userinput>if [ "$a" = "$b" ]</userinput></para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>==</token></term>
	    <listitem>
	      <para>is equal to</para>
	      <para><userinput>if [ "$a" == "$b" ]</userinput></para>
	      <para>This is a synonym for <token>=</token>.</para>

	      <para>
	      <programlisting>[[ $a == z* ]]    # true if $a starts with an "z" (pattern matching)
[[ $a == "z*" ]]  # true if $a is equal to z*

[ $a == z* ]      # file globbing and word splitting take place
[ "$a" == "z*" ]  # true if $a is equal to z*

# Thanks, S.C.</programlisting>
              </para>

	      </listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>!=</token></term>
	    <listitem>
	    <para>is not equal to</para>
	    <para><userinput>if [ "$a" != "$b" ]</userinput></para>
	    <para>This operator uses pattern matching within a <link
	      linkend="dblbrackets">[[ ... ]]</link> construct.</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><anchor id="ltref"><token>&lt;</token></term>
	    <listitem>
	    <para>is less than, in ASCII alphabetical order</para>
	    <para><userinput>if [[ "$a" &lt; "$b" ]]</userinput></para>
	    <para><userinput>if [ "$a" \&lt; "$b" ]</userinput></para>
	    <para>Note that the <quote>&lt;</quote> needs to be
	      escaped within a <userinput>[  ]</userinput>
	      construct.</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><anchor id="gtref"><token>&gt;</token></term>
	    <listitem>
	    <para>is greater than, in ASCII alphabetical order</para>
	    <para><userinput>if [[ "$a" &gt; "$b" ]]</userinput></para>
	    <para><userinput>if [ "$a" \&gt; "$b" ]</userinput></para>
	    <para>Note that the <quote>&gt;</quote> needs to be
	      escaped within a <userinput>[  ]</userinput> construct.</para>  
	    <para>See <xref linkend="bubble"> for an application of this
	      comparison operator.</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-z</token></term>
	    <listitem><para>string is <quote>null</quote>, that is, has zero length</para></listitem>
	  </varlistentry>
	  <varlistentry>
	    <term><token>-n</token></term>
	    <listitem>
	      <para>string is not <quote>null</quote>.</para>
	    
	      <caution><para>The <userinput>-n</userinput> test absolutely
		requires that the string be quoted within the
		test brackets. Using an unquoted string with
		<userinput>! -z</userinput>, or even just the
		unquoted string alone within test brackets (see <xref
		linkend="strtest">) normally works, however, this is
		an unsafe practice. <emphasis>Always</emphasis> quote
		a tested string.
		  <footnote><para>As S.C. points out, in a compound test,
		    even quoting the string variable might not
		    suffice. <userinput>[ -n "$string" -o "$a" =
		    "$b" ]</userinput> may cause an error with some
		    versions of Bash if <varname>$string</varname>
		    is empty.  The safe way is to append an extra
		    character to possibly empty variables, <userinput>[
		    "x$string" != x -o "x$a" = "x$b" ]</userinput>
		    (the <quote>x's</quote> cancel out).</para></footnote>
		</para></caution>

            </listitem>
	    </varlistentry>
	</variablelist>
	
	<example id="ex13">
	  <title>Arithmetic and string comparisons</title>
	  <programlisting>&ex13;</programlisting>
	</example>

	<example id="strtest">
	  <title>Testing whether a string is <emphasis>null</emphasis></title>
	  <programlisting>&strtest;</programlisting>
	</example>
      
	<example id="ex14">
	  <title><command>zmost</command></title>
	  <programlisting>&ex14;</programlisting>
	</example>

	<variablelist id="ccomparison">  
	  <title><anchor id="ccomparison1">compound comparison</title>

	  <varlistentry>
	    <term><token>-a</token></term>
	    <listitem>
	      <para>logical and</para>
	      <para><replaceable>exp1 -a exp2</replaceable> returns true if
		<emphasis>both</emphasis> exp1 and exp2 are true.</para>
	    </listitem>
            </varlistentry>
	  <varlistentry>
	    <term><token>-o</token></term>
	    <listitem>
	      <para>logical or </para>
	      <para><replaceable>exp1 -o exp2</replaceable> returns
		true if either exp1 <emphasis>or</emphasis> exp2 are
		true.</para>
	    </listitem>
	    </varlistentry>
	</variablelist>

       <para>These are similar to the Bash comparison operators
	 <command>&&</command> and <command>||</command>, used
	 within <link linkend="dblbrackets">double brackets</link>.
	   <programlisting>[[ condition1 && condition2 ]]</programlisting>
	 The <command>-o</command> and <command>-a</command> operators
	 work with the <command>test</command> command or occur within
	 single test brackets.
	   <programlisting>if [ "$exp1" -a "$exp2" ]</programlisting>
	   </para>

       <para>Refer to <xref linkend="andor"> and <xref linkend="twodim">
	 to see compound comparison operators in action.</para>

      </sect1> <!-- Comparison operators (binary) -->

      <sect1 id="nestedifthen">
        <title>Nested if/then Condition Tests</title>

       <para>Condition tests using the <command>if/then</command>
	 construct may be nested. The net result is identical to using the
	 <command>&&</command> compound comparison operator above.</para>

       <para><programlisting>if [ condition1 ]
then
  if [ condition2 ]
  then
    do-something  # But only if both "condition1" and "condition2" valid.
  fi  
fi</programlisting></para>  

       <para>See <xref linkend="ex79"> for an example of nested
         <replaceable>if/then</replaceable> condition tests.</para>
	
      </sect1> <!-- Nested if/then Tests -->

      <sect1 id="testtest">
        <title>Testing Your Knowledge of Tests</title>
      <para>The systemwide <filename>xinitrc</filename> file can be used
	to launch the X server. This file contains quite a number of
	<emphasis>if/then</emphasis> tests, as the following excerpt
	shows.</para>

      <para><programlisting>if [ -f $HOME/.Xclients ]; then
  exec $HOME/.Xclients
elif [ -f /etc/X11/xinit/Xclients ]; then
  exec /etc/X11/xinit/Xclients
else
     # failsafe settings.  Although we should never get here
     # (we provide fallbacks in Xclients as well) it can't hurt.
     xclock -geometry 100x100-5+5 &
     xterm -geometry 80x50-50+150 &
     if [ -f /usr/bin/netscape -a -f /usr/share/doc/HTML/index.html ]; then
             netscape /usr/share/doc/HTML/index.html &
     fi
fi</programlisting></para>     

     <para>Explain the <quote>test</quote> constructs in the above excerpt,
       then examine the entire file, <filename>/etc/X11/xinit/xinitrc</filename>,
       and analyze the <emphasis>if/then</emphasis> test constructs
       there. You may need to refer ahead to the discussions of <link
       linkend="grepref">grep</link>, <link linkend="sedref">sed</link>,
       and <link linkend="regexref">regular expressions</link>.</para>


      </sect1> <!-- Testing Your Knowledge of Tests -->

  </chapter> <!-- Tests -->



  <chapter id="operations">
    <title>Operations and Related Topics</title>


     <sect1 id="ops">
      <title>Operators</title>

      <variablelist id="asnop">
        <title><anchor id="asnop1">assignment</title>

	<varlistentry>
	  <term><replaceable>variable assignment</replaceable></term>
	  <listitem><para>Initializing or changing the value of a variable</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <indexterm>
	    <primary>=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>=</secondary>
	  </indexterm>
	  <term>=</term>
	  <listitem>
	  <para>All-purpose assignment operator, which works for both
	    arithmetic and string assignments.</para>

	    <para>
	      <programlisting>var=27
category=minerals  # No spaces allowed after the "=".</programlisting>
	    </para>

            <caution>
	    <para>Do not confuse the <quote>=</quote> assignment
	      operator with the <link linkend="equalsignref">=</link> test
	      operator.</para>

	    <para>
	      <programlisting>#    = as a test operator

if [ "$string1" = "$string2" ]
# if [ "X$string1" = "X$string2" ] is safer,
# to prevent an error message should one of the variables be empty.
# (The prepended "X" characters cancel out.) 
then
   command
fi</programlisting>
	    </para>
	    </caution>


	  </listitem>
	</varlistentry>
      </variablelist>

	<indexterm>
	  <primary>expr</primary>
	</indexterm>
	<indexterm>
	  <primary>command</primary>
	  <secondary>expr</secondary>
	</indexterm>
	<indexterm>
	  <primary>let</primary>
	</indexterm>
	<indexterm>
	  <primary>command</primary>
	  <secondary>let</secondary>
	</indexterm>


      <variablelist id="arops">
        <title><anchor id="arops1">arithmetic operators</title>

	<varlistentry>
	  <term><token>+</token></term>
	  <indexterm>
	    <primary>+</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>+</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>addition</primary>
	  </indexterm>
	  <indexterm>
	    <primary>plus</primary>
	  </indexterm>
	  <listitem><para>plus</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>-</token></term>
	  <indexterm>
	    <primary>-</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>-</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>subtraction</primary>
	  </indexterm>
	  <indexterm>
	    <primary>minus</primary>
	  </indexterm>
	  <listitem><para>minus</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>*</token></term>
	  <indexterm>
	    <primary>*</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>*</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>multiplication</primary>
	  </indexterm>
	  <listitem><para>multiplication</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>/</token></term>
	  <indexterm>
	    <primary>/</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>/</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>division</primary>
	  </indexterm>
	  <listitem><para>division</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="exponentiationref"><token>**</token></term>
	  <indexterm>
	    <primary>**</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>**</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>exponentiation</primary>
	  </indexterm>
	  <listitem>
	  <para>exponentiation
	    <programlisting># Bash, version 2.02, introduced the "**" exponentiation operator.

let "z=5**3"
echo "z = $z"   # z = 125</programlisting>
          </para>	    
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="moduloref"><token>%</token></term>
	  <indexterm>
	    <primary>%</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>%</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>modulo</primary>
	  </indexterm>
	  <listitem>

	  <para>modulo, or mod (returns the remainder of an integer
	    division operation)</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>echo `expr 5 % 3`</userinput>
<computeroutput>2</computeroutput>
	      </screen>
	    </para>

	  <para>This operator finds use in, among other things,
	    generating numbers within a specific range (see <xref
	    linkend="ex21"> and <xref linkend="randomtest">) and
	    formatting program output (see <xref linkend="qfunction"> and
	    <xref linkend="collatz">). It can even be used to generate
	    prime numbers, (see <xref linkend="primes">). Modulo turns
	    up surprisingly often in various numerical recipes.</para>

	    <example id="gcd">
	      <title>Greatest common divisor</title>
	      <programlisting>&gcd;</programlisting>
	    </example>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>+=</token></term>
	  <indexterm>
	    <primary>+=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>+=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>plus-equal</primary>
	  </indexterm>
	  <listitem><para><quote>plus-equal</quote> (increment variable by a constant)</para>
	    <para><userinput>let "var += 5"</userinput> results in
	      <varname>var</varname> being incremented by
	      <literal>5</literal>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>-=</token></term>
	  <indexterm>
	    <primary>-=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>-=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>minus-equal</primary>
	  </indexterm>
	  <listitem><para><quote>minus-equal</quote> (decrement variable by a constant)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>*=</token></term>
	  <indexterm>
	    <primary>*=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>*=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>times-equal</primary>
	  </indexterm>
	  <listitem><para><quote>times-equal</quote> (multiply variable by a constant)</para>
	    <para><userinput>let "var *= 4"</userinput> results in <varname>var</varname>
	    being multiplied by <literal>4</literal>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>/=</token></term>
	  <indexterm>
	    <primary>/=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>/=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>slash-equal</primary>
	  </indexterm>
	  <listitem><para><quote>slash-equal</quote> (divide variable by a constant)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>%=</token></term>
	  <indexterm>
	    <primary>%=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>%=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>mod-equal</primary>
	  </indexterm>
	  <listitem><para><quote>mod-equal</quote> (remainder of dividing variable by a constant)</para>

      <para><emphasis>Arithmetic operators often occur in an
        <link linkend="exprref">expr</link> or <link
        linkend="letref">let</link> expression.</emphasis></para>

	    <example id="arithops">
	      <title>Using Arithmetic Operations</title>
	      <programlisting>&arithops;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

      </variablelist>

      <note><para>Integer variables in Bash are actually signed
	<emphasis>long</emphasis> (32-bit) integers, in the range of
	-2147483648 to 2147483647. An operation that takes a variable
	outside these limits will give an erroneous result.
	  <programlisting>a=2147483646
echo "a = $a"      # a = 2147483646
let "a+=1"         # Increment "a".
echo "a = $a"      # a = 2147483647
let "a+=1"         # increment "a" again, past the limit.
echo "a = $a"      # a = -2147483648
                   #      ERROR (out of range)</programlisting>
	</para></note>

      <caution><para>Bash does not understand floating point arithmetic. It
        treats numbers containing a decimal point as strings.
        <programlisting>a=1.5

let "b = $a + 1.3"  # Error.
# t2.sh: let: b = 1.5 + 1.3: syntax error in expression (error token is ".5 + 1.3")

echo "b = $b"       # b=1</programlisting>

        Use <link linkend="bcref">bc</link> in scripts that that need floating
	point calculations or math library functions.</para></caution>



      <formalpara><title>bitwise operators</title>
      <para>The bitwise operators seldom make an appearance in shell scripts.
	Their chief use seems to be manipulating and testing values
	read from ports or sockets. <quote>Bit flipping</quote> is more
	relevant to compiled languages, such as C and C++, which run
	fast enough to permit its use on the fly.</para></formalpara>

      <variablelist id="bitwsops">
        <title><anchor id="bitwsops1">bitwise operators</title>

	<varlistentry>
	  <term><token><<</token></term>
	  <indexterm>
	    <primary><<</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary><<</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>left shift</primary>
	  </indexterm>
	  <listitem><para>bitwise left shift (multiplies by <literal>2</literal>
	      for each shift position)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token><<=</token></term>
	  <indexterm>
	    <primary><<=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary><<=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>left-shift-equal</primary>
	  </indexterm>
	  <listitem><para><quote>left-shift-equal</quote></para>
	    <para><userinput>let "var <<= 2"</userinput> results in <varname>var</varname>
	    left-shifted <literal>2</literal> bits (multiplied by <literal>4</literal>)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>>></token></term>
	  <indexterm>
	    <primary>>></primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>>></secondary>
	  </indexterm>
	  <indexterm>
	    <primary>right shift</primary>
	  </indexterm>
	  <listitem><para>bitwise right shift (divides by <literal>2</literal>
	      for each shift position)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>>>=</token></term>
	  <indexterm>
	    <primary>>>=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>>>=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>right-shift-equal</primary>
	  </indexterm>
	  <listitem><para><quote>right-shift-equal</quote> (inverse of <token><<=</token>)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>&</token></term>
	  <indexterm>
	    <primary>&</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>&</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>AND</primary>
	    <secondary>bitwise</secondary>
	  </indexterm>
	  <listitem><para>bitwise and</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>&=</token></term>
	  <indexterm>
	    <primary>&=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>&=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>and-equal</primary>
	  </indexterm>
	  <listitem><para><quote>bitwise and-equal</quote></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>|</token></term>
	  <indexterm>
	    <primary>|</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>|</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>OR</primary>
	    <secondary>bitwise</secondary>
	  </indexterm>
	  <listitem><para>bitwise OR</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>|=</token></term>
	  <indexterm>
	    <primary>|=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>|=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>OR-equal</primary>
	  </indexterm>
	  <listitem><para><quote>bitwise OR-equal</quote></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>~</token></term>
	  <indexterm>
	    <primary>~</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>~</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>negate</primary>
	  </indexterm>
	  <listitem><para>bitwise negate</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>!</token></term>
	  <indexterm>
	    <primary>!</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>!</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>NOT</primary>
	  </indexterm>
	  <listitem><para>bitwise NOT</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>^</token></term>
	  <indexterm>
	    <primary>^</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>^</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>XOR</primary>
	  </indexterm>
	  <listitem><para>bitwise XOR</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><token>^=</token></term>
	  <indexterm>
	    <primary>^=</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>^=</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>XOR-equal</primary>
	  </indexterm>
	  <listitem><para><quote>bitwise XOR-equal</quote></para>
	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="logops">
        <title><anchor id="logops1">logical operators</title>

	<varlistentry>
	  <term><token>&&</token></term>
	  <indexterm>
	    <primary>&&</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operator</primary>
	    <secondary>&&</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>AND</primary>
	    <secondary>logical</secondary>
	  </indexterm>
	  <listitem><para>and (logical)</para>
	    <para><programlisting>if [ $condition1 ] && [ $condition2 ]
# Same as:  if [ $condition1 -a $condition2 ]
# Returns true if both condition1 and condition2 hold true...

if [[ $condition1 && $condition2 ]]    # Also works.
# Note that && operator not permitted within [ ... ] construct.</programlisting></para>

	  <note><para><token>&&</token> may also, depending on context, be
	    used in an <link linkend="listconsref">and list</link>
	    to concatenate commands.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="orref"><token>||</token></term>
	  <indexterm>
	    <primary>||</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operator</primary>
	    <secondary>||</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>OR</primary>
	    <secondary>logical</secondary>
	  </indexterm>
	  <listitem><para>or  (logical)</para>
	    <para><programlisting>if [ $condition1 ] || [ $condition2 ]
# Same as:  if [ $condition1 -o $condition2 ]
# Returns true if either condition1 or condition2 holds true...

if [[ $condition1 || $condition2 ]]    # Also works.
# Note that || operator not permitted within [ ... ] construct.</programlisting></para>

	  <note><para>Bash tests the <link linkend="exitstatusref">exit
	    status</link> of each statement linked with a logical
	    operator.</para></note>

	<example id="andor">
	  <title>Compound Condition Tests Using && and ||</title>
       	    <programlisting>&andor;</programlisting>
	 </example>   

	    <para>The <token>&&</token> and <token>||</token> operators also
	      find use in an arithmetic context.</para>
	      
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>echo $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0))</userinput>
<computeroutput>1 0 1 0</computeroutput>
	      </screen>
	    </para>
	      
	  </listitem>
	</varlistentry>

      </variablelist>

      <variablelist id="miscop">
        <title><anchor id="miscop1">miscellaneous operators</title>

	<varlistentry>
	  <term><anchor id="commaop"><token>,</token></term>
	  <indexterm>
	    <primary>,</primary>
	  </indexterm>
	  <indexterm>
	    <primary>operation</primary>
	    <secondary>,</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>linking</primary>
	  </indexterm>
	  <listitem>
	    <para>comma operator</para>
	    <para>The <command>comma operator</command> chains together
	      two or more arithmetic operations. All the operations are
	      evaluated (with possible <emphasis>side effects</emphasis>),
	      but only the last operation is returned.</para>

	     <para>
	     <programlisting>let "t1 = ((5 + 3, 7 - 1, 15 - 4))"
echo "t1 = $t1"               # t1 = 11

let "t2 = ((a = 9, 15 / 3))"  # Set "a" and calculate "t2".
echo "t2 = $t2    a = $a"     # t2 = 5    a = 9</programlisting>
	     </para>

	     <para>The comma operator finds use mainly in <link
	       linkend="forloopref1">for loops</link>. See <xref
	       linkend="forloopc">.</para>

	  </listitem>

	</varlistentry>
      </variablelist>

    </sect1> <!-- Operators -->

    <sect1 id="Numerical-Constants">
      <title>Numerical Constants</title>

      <para><anchor id="numconstants">A shell script interprets a number
	as decimal (base 10), unless that number has a
	special prefix or notation. A number preceded by a
	<replaceable>0</replaceable> is <replaceable>octal</replaceable>
	(base 8). A number preceded by <replaceable>0x</replaceable>
	is <replaceable>hexadecimal</replaceable> (base 16). A number
	with an embedded <replaceable>#</replaceable> evaluates as
	<replaceable>BASE#NUMBER</replaceable> (with range and notational
	restrictions).</para>

	    <example id="numbers">
	      <title>Representation of numerical constants</title>
	      <programlisting>&numbers;</programlisting>
	    </example>

    </sect1> <!-- Numerical-Constants -->

  </chapter> <!-- Operations -->

  </part> <!-- Part 2 (Basics) -->



  <part label="Part 3" id="part3">
    <title>Beyond the Basics</title>

  <chapter id="variables2">
      <title>Variables Revisited</title>


	<para>Used properly, variables can add power and flexibility
	  to scripts. This requires learning their subtleties and
	  nuances.</para>


    <sect1 id="internalvariables">  
      <title>Internal Variables</title>

      <variablelist id="internalvariables1">
	
	<varlistentry>
	  <term><replaceable><link
	  linkend="builtinref">Builtin</link> variables</replaceable></term>
	  <listitem><para>variables affecting bash script behavior</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$BASH</varname></term>
	  <indexterm>
	    <primary>$BASH</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$BASH</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>path to bash</primary>
	  </indexterm>
	  <listitem><para>the path to the <emphasis>Bash</emphasis>
	    binary itself
	      <screen><prompt>bash$ </prompt><userinput>echo $BASH</userinput>
<computeroutput>/bin/bash</computeroutput></screen>
	    </para>
	    
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$BASH_ENV</varname></term>
	  <indexterm>
	    <primary>$BASH_ENV</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$BASH_ENV</secondary>
	  </indexterm>
	  <listitem><para>an <link linkend="envref">environmental
	  variable</link> pointing to a Bash startup file to be read
	  when a script is invoked</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$BASH_VERSINFO[n]</varname></term>
	  <indexterm>
	    <primary>$BASH_VERSINFO</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>version information</secondary>
	  </indexterm>
	  <listitem>
	  <para>a 6-element <link linkend="arrayref">array</link>
	    containing version information about the installed release
	    of Bash. This is similar to <varname>$BASH_VERSION</varname>,
	    below, but a bit more detailed.</para>
	  <para>
	  <programlisting># Bash version info:

for n in 0 1 2 3 4 5
do
  echo "BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}"
done  

# BASH_VERSINFO[0] = 2                      # Major version no.
# BASH_VERSINFO[1] = 05                     # Minor version no.
# BASH_VERSINFO[2] = 8                      # Patch level.
# BASH_VERSINFO[3] = 1                      # Build version.
# BASH_VERSINFO[4] = release                # Release status.
# BASH_VERSINFO[5] = i386-redhat-linux-gnu  # Architecture
                                            # (same as $MACHTYPE).</programlisting>
	  </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$BASH_VERSION</varname></term>
	  <indexterm>
	    <primary>$BASH_VERSION</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$BASH_VERSION</secondary>
	  </indexterm>
	  <listitem><para>the version of Bash installed on the system</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>echo $BASH_VERSION</userinput>
<computeroutput>2.04.12(1)-release</computeroutput>
	      </screen>
	    </para>

	  <para>
	      <screen><prompt>tcsh% </prompt><userinput>echo $BASH_VERSION</userinput>
<computeroutput>BASH_VERSION: Undefined variable.</computeroutput>
	      </screen>
	    </para>

	  <para>Checking $BASH_VERSION is a good method of determining which
	    shell is running. <link linkend="shellvarref">$SHELL</link>
	    does not necessarily give the correct answer.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="dirstackref"><varname>$DIRSTACK</varname></term>
	  <indexterm>
	    <primary>$DIRSTACK</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$DIRSTACK</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>directory stack</primary>
	  </indexterm>
	  <indexterm>
	    <primary>directory</primary>
	    <secondary>stack</secondary>
	  </indexterm>
	  <listitem><para>the top value in the directory stack
	    (affected by <link linkend="pushdref">pushd</link> and <link
	    linkend="popdref">popd</link>)</para> <para>This builtin
	    variable corresponds to the <link linkend="dirsd">dirs</link>
	    command, however <command>dirs</command> shows the entire
	    contents of the directory stack.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$EDITOR</varname></term>
	  <indexterm>
	    <primary>$EDITOR</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$EDITOR</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>editor</primary>
	  </indexterm>
	  <listitem><para>the default editor invoked by a script, usually
	      <command>vi</command> or <command>emacs</command>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="euidref"><varname>$EUID</varname></term>
	  <indexterm>
	    <primary>$EUID</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$EUID</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>effective user ID</primary>
	  </indexterm>
	  <listitem><para><quote>effective</quote> user ID number</para>
	    <para>Identification number of whatever identity the
	      current user has assumed, perhaps by means of <link
	      linkend="suref">su</link>.</para>
	    <caution><para>The <varname>$EUID</varname> is not necessarily
	      the same as the <link
	      linkend="uidref">$UID</link>.</para></caution>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$FUNCNAME</varname></term>
	  <indexterm>
	    <primary>$FUNCNAME</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>function</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>name</primary>
	  </indexterm>
	  <listitem>
	    <para>name of the current function</para>
	    <para><programlisting>xyz23 ()
{
  echo "$FUNCNAME now executing."  # xyz23 now executing.
}

xyz23

echo "FUNCNAME = $FUNCNAME"        # FUNCNAME =
                                   # Null value outside a function.</programlisting>
            </para>

	  </listitem>
	</varlistentry>

        <varlistentry>
	  <term><varname>$GLOBIGNORE</varname></term>
	  <indexterm>
	    <primary>$GLOBIGNORE</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>globbing</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>ignore</primary>
	  </indexterm>
	  <listitem><para>A list of filename patterns to be excluded from
	    matching in <link linkend="globbingref">globbing</link>.</para>
	  </listitem>
	</varlistentry>

        <varlistentry>
	  <term><anchor id="groupsref"><varname>$GROUPS</varname></term>
	  <indexterm>
	    <primary>$GROUPS</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$GROUPS</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>groups</primary>
	  </indexterm>
	  <listitem><para>groups current user belongs to</para>
	    <para>This is a listing (array) of the group id numbers for
	      current user, as  recorded in
	      <filename>/etc/passwd</filename>.
	    </para>

	    <para>
	      <screen>
<prompt>root# </prompt><userinput>echo $GROUPS</userinput>
<computeroutput>0</computeroutput>


<prompt>root# </prompt><userinput>echo ${GROUPS[1]}</userinput>
<computeroutput>1</computeroutput>


<prompt>root# </prompt><userinput>echo ${GROUPS[5]}</userinput>
<computeroutput>6</computeroutput>
	      </screen>
	      </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="homedirref"><varname>$HOME</varname></term>
	  <indexterm>
	    <primary>$HOME</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$HOME</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>home directory</primary>
	  </indexterm>
	  <indexterm>
	    <primary>directory</primary>
	    <secondary>home</secondary>
	  </indexterm>
	  <listitem><para>home directory of the user, usually <filename
	    class="directory">/home/username</filename> (see <xref
	    linkend="ex6">)</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="hostnameref"><varname>$HOSTNAME</varname></term>
	  <indexterm>
	    <primary>$HOSTNAME</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$HOSTNAME</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>system name</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>name</secondary>
	  </indexterm>
	  <listitem>
	  <para>The <link linkend="hnameref">hostname</link> command
	    assigns the system name at bootup in an init script.
	    However, the <function>gethostname()</function> function
	    sets the Bash internal variable <varname>$HOSTNAME</varname>.
	    See also <xref linkend="ex6">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$HOSTTYPE</varname></term>
	  <indexterm>
	    <primary>$HOSTTYPE</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$HOSTTYPE</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>host type</primary>
	  </indexterm>
	  <listitem><para>host type</para>
	    <para>Like <link linkend="machtyperef">$MACHTYPE</link>,
	      identifies the system hardware.</para>
	    <screen><prompt>bash$ </prompt><userinput>echo $HOSTTYPE</userinput>
<computeroutput>i686</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="ifsref"><varname>$IFS</varname></term>
	  <indexterm>
	    <primary>$IFS</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$IFS</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>input field separator</primary>
	  </indexterm>
	  <listitem><para>input field separator</para>
	    <para>This defaults to <link
	      linkend="whitespaceref">whitespace</link> (space,
	      tab, and newline), but may be changed, for example,
	      to parse a comma-separated data file.  Note that
	      <link linkend="appref">$*</link> uses the first
	      character held in <varname>$IFS</varname>.  See <xref
	      linkend="weirdvars">.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>echo $IFS | cat -vte</userinput>
<computeroutput>$</computeroutput>


<prompt>bash$ </prompt><userinput>bash -c 'set w x y z; IFS=":-;"; echo "$*"'</userinput>
<computeroutput>w:x:y:z</computeroutput>
	      </screen>
	  </para>

	  <caution><para><varname>$IFS</varname> does not handle whitespace
	    the same as it does other characters.

	  <example id="ifsh">
	    <title>$IFS and whitespace</title>
	    <programlisting>&ifsh;</programlisting>
	  </example>

	  </para></caution>

	  <para>(Thanks, S. C., for clarification and examples.)</para> 

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$IGNOREEOF</varname></term>
	  <indexterm>
	    <primary>$IGNOREEOF</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$IGNOREEOF</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>Ignore EOF</primary>
	  </indexterm>
	  <listitem><para>ignore EOF: how many end-of-files (control-D)
	    the shell will ignore before logging out.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$LC_COLLATE</varname></term>
	  <indexterm>
	    <primary>$LC_COLLATE</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$LC_COLLATE</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>lowercase collate</primary>
	  </indexterm>
	  <listitem>

	  <para>Often set in the <filename>.bashrc</filename> or
	    <filename>/etc/profile</filename> files, this
	    variable controls collation order in filename
	    expansion and pattern matching. If mishandled,
	    <varname>LC_COLLATE</varname> can cause unexpected results
	    in <link linkend="globbingref">filename
	    globbing</link>.</para>

	  <note><para>As of version 2.05 of Bash,
	    filename globbing no longer distinguishes between lowercase
	    and uppercase letters in a character range between
	    brackets. For example, <command>ls [A-M]*</command>
	    would match both <filename>File1.txt</filename>
	    and <filename>file1.txt</filename>. To revert to
	    the customary behavior of bracket matching, set
	    <varname>LC_COLLATE</varname> to <option>C</option>
	    by an <userinput>export LC_COLLATE=C</userinput>
	    in <filename>/etc/profile</filename> and/or
	    <filename>~/.bashrc</filename>.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$LC_CTYPE</varname></term>
	  <indexterm>
	    <primary>$LC_CTYPE</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$LC_CTYPE</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>lowercase character type</primary>
	  </indexterm>
	  <listitem>

	  <para>This internal variable controls character interpretation
	    in <link linkend="globbingref">globbing</link> and pattern
	    matching.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$LINENO</varname></term>
	  <indexterm>
	    <primary>$LINENO</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$LINENO</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>line number</primary>
	  </indexterm>
	  <listitem><para>This variable is the line number of the shell
	    script in which this variable appears. It has significance only
	    within the script in which it appears, and is chiefly useful for
	    debugging purposes.</para>
	  <para><programlisting># *** BEGIN DEBUG BLOCK ***
last_cmd_arg=$_  # Save it.

echo "At line number $LINENO, variable \"v1\" = $v1"
echo "Last command argument processed = $last_cmd_arg"
# *** END DEBUG BLOCK ***</programlisting></para>
	      
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="machtyperef"><varname>$MACHTYPE</varname></term>
	  <indexterm>
	    <primary>$MACHTYPE</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$MACHTYPE</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>machine type</primary>
	  </indexterm>
	  <listitem><para>machine type</para>
	    <para>Identifies the system hardware.</para>
	    <screen><prompt>bash$ </prompt><userinput>echo $MACHTYPE</userinput>
<computeroutput>i686</computeroutput></screen>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="oldpwd"><varname>$OLDPWD</varname></term>
	  <indexterm>
	    <primary>$OLDPWD</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$OLDPWD</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>previous working directory</primary>
	  </indexterm>
	  <indexterm>
	    <primary>directory</primary>
	    <secondary>working</secondary>
	  </indexterm>
	  <listitem><para>old working directory
	  (<quote>OLD-print-working-directory</quote>,
	    previous directory you were in)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$OSTYPE</varname></term>
	  <indexterm>
	    <primary>$OSTYPE</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$OSTYPE</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>os type</primary>
	  </indexterm>
	  <listitem><para>operating system type</para>
	    <screen><prompt>bash$ </prompt><userinput>echo $OSTYPE</userinput>
<computeroutput>linux</computeroutput></screen>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="pathref"><varname>$PATH</varname></term>
	  <indexterm>
	    <primary>$PATH</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PATH</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>path to binaries</primary>
	  </indexterm>
	  <listitem><para>path to binaries, usually 
	      <filename class="directory">/usr/bin/</filename>, 
	      <filename class="directory">/usr/X11R6/bin/</filename>, 
	      <filename class="directory">/usr/local/bin</filename>, etc.</para>

	    <para>When given a command, the shell automatically does
	      a hash table search on the directories listed in the
	      <emphasis>path</emphasis> for the executable. The path
	      is stored in the <link linkend="envref">environmental
	      variable</link>, <varname>$PATH</varname>, a list
	      of directories, separated by colons. Normally,
	      the system stores the <varname>$PATH</varname>
	      definition in <filename>/etc/profile</filename>
	      and/or <filename>~/.bashrc</filename> (see <xref
	      linkend="files">).</para>

	      <para><screen><prompt>bash$ </prompt><command>echo $PATH</command>
<computeroutput>/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/sbin:/usr/sbin</computeroutput></screen>
              </para>

	    <para><userinput>PATH=${PATH}:/opt/bin</userinput> appends
	      the <filename class="directory">/opt/bin</filename>
	      directory to the current path. In a script, it may be
	      expedient to temporarily add a directory to the path
	      in this way. When the script exits, this restores the
	      original <varname>$PATH</varname> (a child process, such
	      as a script, may not change the environment of the parent
	      process, the shell).</para>

	    <note><para>The current <quote>working directory</quote>, 
	      <filename class="directory">./</filename>, is usually
	      omitted from the <varname>$PATH</varname> as a security
	      measure.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$PIPESTATUS</varname></term>
	  <indexterm>
	    <primary>$PIPESTATUS</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>pipe</secondary>
	  </indexterm>
	  <listitem>
	  <para>Exit status of last executed
	    <emphasis>foreground</emphasis> <link
	    linkend="piperef">pipe</link>. Interestingly enough,
	    this does not give the same result as the <link
	    linkend="exitstatusref">exit status</link> of the last
	    executed command.</para>

	      <para>
	      <screen>
<prompt>bash$ </prompt><userinput>echo $PIPESTATUS</userinput>
<computeroutput>0</computeroutput>

<prompt>bash$ </prompt><userinput>ls -al | bogus_command</userinput>
<computeroutput>bash: bogus_command: command not found</computeroutput>
<prompt>bash$ </prompt><userinput>echo $PIPESTATUS</userinput>
<computeroutput>141</computeroutput>

<prompt>bash$ </prompt><userinput>ls -al | bogus_command</userinput>
<computeroutput>bash: bogus_command: command not found</computeroutput>
<prompt>bash$ </prompt><userinput>echo $?</userinput>
<computeroutput>127</computeroutput>
	      </screen>
	      </para>

	      <caution>

	      <para>
	      The <varname>$PIPESTATUS</varname> variable
              may contain an erroneous <errorcode>0</errorcode> value
              in a login shell.
              </para>

	      <para>
	      <screen>
<prompt>tcsh% </prompt><userinput>bash</userinput>

<prompt>bash$ </prompt><userinput>who | grep nobody | sort</userinput>
<prompt>bash$ </prompt><userinput>echo ${PIPESTATUS[*]}</userinput>
<computeroutput>0</computeroutput>
	      </screen>
	      </para>

	      <para>
	      The above lines contained in a script would produce the expected
	      <computeroutput>0 1 0</computeroutput> output.
              </para>

	      <para>
	      Thank you, Wayne Pollock for pointing this out and supplying the
	      above example.
	      </para>

	      </caution>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="ppidref"><varname>$PPID</varname></term>
	  <indexterm>
	    <primary>$PPID</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PPID</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>process id</primary>
	  </indexterm>
	  <listitem><para></para>
	    <para>The <varname>$PPID</varname> of a process is
	    the process ID (<varname>pid</varname>) of its parent process.

	      <footnote><para>The PID of the currently running script is
	      <varname>$$</varname>, of course.</para></footnote>
	      </para>

	    <para>Compare this with the <link
	      linkend="pidofref">pidof</link> command.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$PROMPT_COMMAND</varname></term>
	  <indexterm>
	    <primary>$PROMPT_COMMAND</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>prompt</secondary>
	  </indexterm>
	  <listitem>
	    <para>A variable holding a command to be executed
	      just before the primary prompt, <varname>$PS1</varname>
	      is to be displayed.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="ps1ref"><varname>$PS1</varname></term>
	  <indexterm>
	    <primary>$PS1</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PS1</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>prompt</primary>
	  </indexterm>
	  <listitem><para>This is the main prompt, seen at the command line.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$PS2</varname></term>
	  <indexterm>
	    <primary>$PS2</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PS2</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>prompt</primary>
	    <secondary>secondary</secondary>
	  </indexterm>
	  <listitem>
	    <para><anchor id="secpromptref"></para>
	    <para>The secondary prompt, seen when additional input is
	      expected. It displays as <quote>&gt;</quote>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$PS3</varname></term>
	  <indexterm>
	    <primary>$PS3</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PS3</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>prompt</primary>
	    <secondary>tertiary</secondary>
	  </indexterm>
	  <listitem><para>The tertiary prompt, displayed in a
	    <link linkend="selectref">select</link> loop (see <xref
	    linkend="ex31">).</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$PS4</varname></term>
	  <indexterm>
	    <primary>$PS4</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PS4</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>prompt</primary>
	    <secondary>quartenary</secondary>
	  </indexterm>
	  <listitem>
	  <para>The quartenary prompt, shown at the beginning of
	    each line of output when invoking a script with the
	    <token>-x</token> <link linkend="optionsref">option</link>.
	    It displays as <quote>+</quote>.</para>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="pwdref"><varname>$PWD</varname></term>
	  <indexterm>
	    <primary>$PWD</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PWD</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>working directory</primary>
	  </indexterm>
	  <indexterm>
	    <primary>directory</primary>
	    <secondary>working</secondary>
	  </indexterm>
	  <listitem>
	  <para>working directory (directory you are in at the time)</para>
	  <para>This is the analog to the <link linkend="pwd2ref">pwd</link>
	    builtin command.</para>
          <para><programlisting>&wipedir;</programlisting></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="replyref"><varname>$REPLY</varname></term>
	  <indexterm>
	    <primary>$REPLY</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$REPLY</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>default value of read</primary>
	  </indexterm>
	  <indexterm>
	    <primary>reply</primary>
	    <secondary>read</secondary>
	  </indexterm>
	  <listitem><para>The default value when a variable is not
	    supplied to <link linkend="readref">read</link>. Also
	    applicable to <link linkend="selectref">select</link> menus,
	    but only supplies the item number of the variable chosen,
	    not the value of the variable itself.</para>
	     <para><programlisting>&reply;</programlisting></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$SECONDS</varname></term>
	  <indexterm>
	    <primary>$SECONDS</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$SECONDS</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>seconds execution time</primary>
	  </indexterm>
	  <indexterm>
	    <primary>runtime</primary>
	    <secondary>seconds</secondary>
	  </indexterm>
	  <listitem><para>The number of seconds the script has been running.</para>
	     <para><programlisting>&seconds;</programlisting></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$SHELLOPTS</varname></term>
	  <indexterm>
	    <primary>$SHELLOPTS</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$SHELLOPTS</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>shell options</primary>
	  </indexterm>
	  <listitem>
	    <para>the list of enabled shell <link
	      linkend="optionsref">options</link>, a readonly variable
	      <screen><prompt>bash$ </prompt><userinput>echo $SHELLOPTS</userinput>
<computeroutput>braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$SHLVL</varname></term>
	  <indexterm>
	    <primary>$SHLVL</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$SHLVL</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>shell level</primary>
	  </indexterm>
	  <listitem><para>Shell level, how deeply Bash is nested.  If,
	    at the command line, $SHLVL is 1, then in a script it will
	    increment to 2.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$TMOUT</varname></term>
	  <indexterm>
	    <primary>$TMOUT</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$TMOUT</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>timeout interval</primary>
	  </indexterm>
	  <listitem><para>If the <replaceable>$TMOUT</replaceable>
	  environmental variable is set to a non-zero value
	  <emphasis>time</emphasis>, then the shell prompt will time out
	  after <emphasis>time</emphasis> seconds. This will cause a
	  logout.</para>

	  <note><para>Unfortunately, this works only while waiting
	    for input at the shell prompt console or in an xterm. While
	    it would be nice to speculate on the uses of this
	    internal variable for timed input, for example in
	    combination with <link linkend="readref">read</link>,
	    <replaceable>$TMOUT</replaceable> does not work
	    in that context and is virtually useless for shell
	    scripting. (Reportedly the <emphasis>ksh</emphasis> version
	    of a timed <command>read</command> does work.)</para></note>

	  <para>Implementing timed input in a script is certainly
	    possible, but may require complex machinations. One method
	    is to set up a timing loop to signal the script when it
	    times out.	This also requires a signal handling routine to
	    trap (see <xref linkend="ex76">) the interrupt generated by
	    the timing loop (whew!).</para>

	    <example id="tmdin">
	      <title>Timed Input</title>
	      <programlisting>&tmdin;</programlisting>
	    </example>	    

	  <para>An alternative is using <link
	    linkend="sttyref">stty</link>.</para>

	    <example id="timeout">
	      <title>Once more, timed input</title>
	      <programlisting>&timeout;</programlisting>
	    </example>	    

	  <para>Perhaps the simplest method is using the
	    <option>-t</option> option to <link
	    linkend="readref">read</link>.</para>
	    
	    <example id="tout">
	      <title>Timed <command>read</command></title>
	      <programlisting>&tout;</programlisting>
	    </example>	    
	   

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="uidref"><varname>$UID</varname></term>
	  <indexterm>
	    <primary>$UID</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$UID</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>user ID</primary>
	  </indexterm>
	  <listitem><para>user ID number</para>

	    <para>current user's user identification number, as
	      recorded in <filename>/etc/passwd</filename>
	    </para>

	    <para>This is the current user's real id, even if she has
	      temporarily assumed another identity through <link
	      linkend="suref">su</link>. <varname>$UID</varname> is a
	      readonly variable, not subject to change from the command
	      line or within a script, and is the counterpart to the
	      <link linkend="idref">id</link> builtin.</para>

            <example id="amiroot">
	      <title>Am I root?</title>
	      <programlisting>&amiroot;</programlisting>
            </example>

	    <para>See also <xref linkend="ex2">.</para>


	<!-- Nest note within last entry  -->
	<note>
	<para>The variables <varname>$ENV</varname>,
	  <varname>$LOGNAME</varname>, <varname>$MAIL</varname>,
	  <varname>$TERM</varname>, <varname>$USER</varname>, and
	  <varname>$USERNAME</varname> are <emphasis>not</emphasis>
	  Bash <link linkend="builtinref">builtins</link>. These are,
	  however, often set as <link linkend="envref">environmental
	  variables</link> in one of the Bash <link
	  linkend="filesref1">startup files</link>.  <anchor
	  id="shellvarref"><varname>$SHELL</varname>,
	  the name of the user's login shell, may be set from
	  <filename>/etc/passwd</filename> or in an <quote>init</quote>
	  script, and it is likewise not a Bash builtin.</para>
	      <para>
	      <screen>
<prompt>tcsh% </prompt><userinput>echo $LOGNAME</userinput>
<computeroutput>bozo</computeroutput>
<prompt>tcsh% </prompt><userinput>echo $SHELL</userinput>
<computeroutput>/bin/tcsh</computeroutput>
<prompt>tcsh% </prompt><userinput>echo $TERM</userinput>
<computeroutput>rxvt</computeroutput>

<prompt>bash$ </prompt><userinput>echo $LOGNAME</userinput>
<computeroutput>bozo</computeroutput>
<prompt>bash$ </prompt><userinput>echo $SHELL</userinput>
<computeroutput>/bin/tcsh</computeroutput>
<prompt>bash$ </prompt><userinput>echo $TERM</userinput>
<computeroutput>rxvt</computeroutput>
	      </screen>
	      </para>
	  </note>

	<!-- Nest note after $USER  -->

	  </listitem>
	</varlistentry>


      </variablelist>

	<!-- Last entry of intrinsic BASH variables -->

      <variablelist id="posparmslist">
        <title>Positional Parameters</title>

	<varlistentry>
	  <term><anchor id="posparamref"><varname>$0</varname>, <varname>$1</varname>,
	  <varname>$2</varname>, etc.</term>
	  <indexterm>
	    <primary>$0</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$0</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>positional parameter</primary>
	  </indexterm>
	  <indexterm>
	    <primary>parameter</primary>
	    <secondary>positional</secondary>
	  </indexterm>
	  <listitem>
	    <para>positional parameters, passed from command
	      line to script, passed to a function, or <link
	      linkend="setref">set</link> to a variable (see <xref
	      linkend="ex17"> and <xref linkend="ex34">)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$#</varname></term>
	  <indexterm>
	    <primary>$#</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$#</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>positional parameter</primary>
	    <secondary>number of</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>parameter</primary>
	    <secondary>positional</secondary>
	    <tertiary>number of</tertiary>
	  </indexterm>
	  <listitem><para>number of command line arguments
		<footnote><para>The words <quote>argument</quote>
		and <quote>parameter</quote> are often used
		interchangeably. In the context of this document, they
		have the same precise meaning, that of a variable passed
		to a script or function.</para></footnote>
	    or positional parameters (see <xref linkend="ex4">)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="appref"><varname>$*</varname></term>
	  <indexterm>
	    <primary>$*</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$*</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>positional parameter</primary>
	    <secondary>all</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>parameter</primary>
	    <secondary>positional</secondary>
	    <tertiary>all</tertiary>
	  </indexterm>
	  <listitem>
	  <para>All of the positional parameters, seen as a single word</para>
	  <note><para><quote><varname>$*</varname></quote> must be
	    quoted.</para></note>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$@</varname></term>
	  <indexterm>
	    <primary>$@</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$*</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>positional parameter</primary>
	    <secondary>all</secondary>
	  </indexterm>

	  <listitem>
	  
	  <para>Same as <token>$*</token>, but each parameter is a
	      quoted string, that is, the parameters are passed on
	      intact, without interpretation or expansion. This means,
	      among other things, that each parameter in the argument
	      list is seen as a separate word.</para>

	  <note><para>Of course, <quote><varname>$@</varname></quote>
	    should be quoted.</para></note>

	    <example id="arglist">
	      <title><command>arglist</command>: Listing arguments with $* and $@</title>
	      <programlisting>&arglist;</programlisting>
	    </example>   

	    <para>Following a <command>shift</command>, the
	      <varname>$@</varname> holds the remaining command-line
	      parameters, lacking the previous <varname>$1</varname>,
	      which was lost.
	        <programlisting>#!/bin/bash
# Invoke with ./scriptname 1 2 3 4 5

echo "$@"    # 1 2 3 4 5
shift
echo "$@"    # 2 3 4 5
shift
echo "$@"    # 3 4 5

# Each "shift" loses parameter $1.
# "$@" then contains the remaining parameters.</programlisting>
            </para>


	    <para>The <varname>$@</varname> special parameter finds
	      use as a tool for filtering input into shell scripts. The
	      <command>cat "$@"</command> construction accepts input
	      to a script either from <filename>stdin</filename> or
	      from files given as parameters to the script. See <xref
	      linkend="rot13"> and <xref linkend="cryptoquote">.</para>


	    <caution><para>The <varname>$*</varname> and <varname>$@</varname>
	      parameters sometimes display inconsistent and
	      puzzling behavior, depending on the setting of <link
	      linkend="ifsref">$IFS</link>.</para></caution>

	    <example id="incompat">
	      <title>Inconsistent <varname>$*</varname> and <varname>$@</varname> behavior</title>
	      <programlisting>&incompat;</programlisting>
	    </example>	    

	    <note><para>The <command>$@</command> and <command>$*</command>
	      parameters differ only when between double quotes.</para></note>

	    <example id="ifsempty">
	      <title><varname>$*</varname> and <varname>$@</varname> when
	        <varname>$IFS</varname> is empty</title>
	      <programlisting>&ifsempty;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

    </variablelist>	

      <variablelist id="otherspecparams">
        <title>Other Special Parameters</title>

	<varlistentry>
	  <term><anchor id="flpref"><varname>$-</varname></term>
	  <indexterm>
	    <primary>$-</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$-</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>flags</primary>
	  </indexterm>
	  <listitem>
	    <para>Flags passed to script (using <link
	      linkend="setref">set</link>). See <xref linkend="ex34">.</para>
	    <caution><para>This was originally a <emphasis>ksh</emphasis>
	      construct adopted into Bash, and unfortunately it does not
	      seem to work reliably in Bash scripts. One possible use
	      for it is to have a script <link linkend="iitest">self-test
	      whether it is interactive</link>.</para></caution>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><varname>$!</varname></term>
	  <indexterm>
	    <primary>$!</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$!</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>PID</primary>
	    <secondary>last job background</secondary>
	  </indexterm>
	  <listitem>

	    <para>PID (process ID) of last job run in background</para>

	    <para>
	      <programlisting>LOG=$0.log

COMMAND1="sleep 100"

echo "Logging PIDs background commands for script: $0" >> "$LOG"
# So they can be monitored, and killed as necessary.
echo >> "$LOG"

# Logging commands.

echo -n "PID of \"$COMMAND1\":  " >> "$LOG"
${COMMAND1} &
echo $! >> "$LOG"
# PID of "sleep 100":  1506

# Thank you, Jacques Lederer, for suggesting this.</programlisting>
            </para>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="underscoreref"><varname>$_</varname></term>
	  <indexterm>
	    <primary>$_</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$_</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>underscore</primary>
	    <secondary>last argument</secondary>
	  </indexterm>
	  <listitem>
	      <para>Special variable set to last argument of previous command
	        executed.</para>


      <example id="uscref">
	<title>Underscore variable</title>
        <programlisting>#!/bin/bash

echo $_              # /bin/bash
                     # Just called /bin/bash to run the script.

du >/dev/null        # So no output from command.
echo $_              # du

ls -al >/dev/null    # So no output from command.
echo $_              # -al  (last argument)

:
echo $_              # :</programlisting></example>
	    </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="xstatvarref"><varname>$?</varname></term>
	  <indexterm>
	    <primary>$?</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$?</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>exit status</primary>
	  </indexterm>
	  <listitem><para><link linkend="exitstatusref">Exit status</link>
	    of a command, <link linkend="functionref">function</link>,
	    or the script itself (see <xref linkend="max">)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="proccid"><varname>$$</varname></term>
	  <indexterm>
	    <primary>$$</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$$</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>PID</primary>
	    <secondary>of script</secondary>
	  </indexterm>
	  <listitem><para>Process ID of the script itself. The
	  <varname>$$</varname> variable often finds use
	    in scripts to construct <quote>unique</quote>
	    temp file names (see <xref linkend="ftpget">, <xref
	    linkend="online">, <xref linkend="derpm">, and <xref
	    linkend="selfdestruct">). This is usually simpler than
	    invoking <link linkend="mktempref">mktemp</link>.</para>
	      
	  </listitem>
	</varlistentry>

    </variablelist>	


    </sect1> <!-- Internal Variables -->

    <sect1 id="String-Manipulation">
      <title>Manipulating Strings</title>

            <para><anchor id="stringmanip"></para> 

	    <para>Bash supports a surprising number of string manipulation
	      operations.  Unfortunately, these tools lack
	      a unified focus. Some are a subset of <link
	      linkend="paramsubref">parameter substitution</link>, and
	      others fall under the functionality of the UNIX <link
	      linkend="exprref">expr</link> command. This results in
	      inconsistent command syntax and overlap of functionality,
	      not to mention confusion.</para>

      <variablelist id="stringlength">
        <title>String Length</title>

	<varlistentry>
	  <term>${#string}</term>
	  <indexterm>
	    <primary>string length</primary>
	    <secondary>parameter substitution</secondary>
	  </indexterm>

	  <listitem><para></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr length $string</term>
	  <indexterm>
	    <primary>string length</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem><para></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr "$string" : '.*'</term>
	  <indexterm>
	    <primary>string length</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>
	  <para>
	  <programlisting>stringZ=abcABC123ABCabc

echo ${#stringZ}                 # 15
echo `expr length $stringZ`      # 15
echo `expr "$stringZ" : '.*'`    # 15</programlisting>
	  </para>
	  </listitem>

	</varlistentry>

      </variablelist>

	    <example id="paragraphspace">
	      <title>Inserting a blank line between paragraphs in a text file</title>
	      <programlisting>&paragraphspace;</programlisting>
	    </example>

      <variablelist id="lengthsubstring">
        <title>Length of Matching Substring at Beginning of String</title>
	
	<varlistentry>
	  <term>expr match "$string" '$substring'</term>
	  <indexterm>
	    <primary>substring length</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>
	  <para><replaceable>$substring</replaceable> is a <link
	    linkend="regexref">regular expression</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr "$string" : '$substring'</term>
	  <indexterm>
	    <primary>substring length</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>
	  <para><replaceable>$substring</replaceable> is a regular
	    expression.</para>
	  <para>

	  <programlisting>stringZ=abcABC123ABCabc
#       |------|

echo `expr match "$stringZ" 'abc[A-Z]*.2'`   # 8
echo `expr "$stringZ" : 'abc[A-Z]*.2'`       # 8</programlisting>
          </para>
	  </listitem>
	</varlistentry>

      </variablelist>

      <variablelist id="substringindex">
        <title>Index</title>

	<varlistentry>
	  <term>expr index $string $substring</term>
	  <indexterm>
	    <primary>substring index</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>

	  <para>Numerical position in $string of first character in 
	    $substring that matches.</para>

	  <para><programlisting>stringZ=abcABC123ABCabc
echo `expr index "$stringZ" C12`             # 6
                                             # C position.

echo `expr index "$stringZ" 1c`              # 3
# 'c' (in #3 position) matches before '1'.</programlisting></para>

          <para>This is the near equivalent of
            <emphasis>strchr()</emphasis> in C.</para>
	  </listitem>
	</varlistentry>

      </variablelist>

      <variablelist id="substringextraction">
        <title>Substring Extraction</title>

	<varlistentry>
	  <term>${string:position}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>extraction</secondary>
	  </indexterm>

	  <listitem>
	  <para>Extracts substring from <replaceable>$string</replaceable> at
	    <replaceable>$position</replaceable>.</para>
	  <para>If the <varname>$string</varname> parameter is
	    <quote><token>*</token></quote>
	    or <quote><token>@</token></quote>, then this extracts the
	    <link linkend="posparamref">positional parameters</link>,
	       <footnote><para>This applies to either command line
	       arguments or parameters passed to a <link
	       linkend="functionref">function</link>.</para></footnote>
	    starting at <varname>$position</varname>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string:position:length}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>extraction</secondary>
	  </indexterm>

	  <listitem>
	  <para>Extracts <replaceable>$length</replaceable> characters
	    of substring from <replaceable>$string</replaceable> at
	    <replaceable>$position</replaceable>.</para>
	  <para>
	  <programlisting>stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                            # abcABC123ABCabc
echo ${stringZ:1}                            # bcABC123ABCabc
echo ${stringZ:7}                            # 23ABCabc

echo ${stringZ:7:3}                          # 23A
                                             # Three characters of substring.



# Is it possible to index from the right end of the string?
    
echo ${stringZ:-4}                           # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . .

echo ${stringZ:(-4)}                         # Cabc 
echo ${stringZ: -4}                          # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.

# Thank you, Dan Jacobson, for pointing this out.</programlisting>
	  </para>
	  <para>If the <varname>$string</varname> parameter is
	    <quote><token>*</token></quote> or
	    <quote><token>@</token></quote>, then this extracts a maximum
	    of <varname>$length</varname> positional parameters, starting
	    at <varname>$position</varname>.</para>

	  <para>
	  <programlisting>echo ${*:2}          # Echoes second and following positional parameters.
echo ${@:2}          # Same as above.

echo ${*:2:3}        # Echoes three positional parameters, starting at second.</programlisting>
	  </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr substr $string $position $length</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>extraction expr</secondary>
	  </indexterm>

	  <listitem>
	  
	  <para>Extracts <replaceable>$length</replaceable> characters
	    from <replaceable>$string</replaceable> starting at
	    <replaceable>$position</replaceable>.</para>
	  
	  <para>
	  <programlisting>stringZ=abcABC123ABCabc
#       123456789......
#       1-based indexing.

echo `expr substr $stringZ 1 2`              # ab
echo `expr substr $stringZ 4 3`              # ABC</programlisting>
          </para>

	  <para><anchor id="exprparen"></para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr match "$string" '\($substring\)'</term>
	  <indexterm>
	    <primary>substring extraction</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>
	  <para>Extracts <replaceable>$substring</replaceable>
	    at beginning of <replaceable>$string</replaceable>,
	    where <replaceable>$substring</replaceable> is a <link
	    linkend="regexref">regular expression</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr "$string" : '\($substring\)'</term>
	  <indexterm>
	    <primary>substring extraction</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>

	  <para>Extracts <replaceable>$substring</replaceable>
	    at beginning of <replaceable>$string</replaceable>,
	    where <replaceable>$substring</replaceable> is a regular
	    expression.</para>

	    <para>
	    <programlisting>stringZ=abcABC123ABCabc
#       =======	    

echo `expr match "$stringZ" '\(.[b-c]*[A-Z]..[0-9]\)'`   # abcABC1
echo `expr "$stringZ" : '\(.[b-c]*[A-Z]..[0-9]\)'`       # abcABC1
echo `expr "$stringZ" : '\(.......\)'`                   # abcABC1
# All of the above forms give an identical result.</programlisting>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr match "$string" '.*\($substring\)'</term>
	  <indexterm>
	    <primary>substring extraction</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>
	  <para>Extracts <replaceable>$substring</replaceable>
	    at <emphasis>end</emphasis> of
	    <replaceable>$string</replaceable>, where
	    <replaceable>$substring</replaceable> is a regular
	    expression.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>expr "$string" : '.*\($substring\)'</term>
	  <indexterm>
	    <primary>substring extraction</primary>
	    <secondary>expr</secondary>
	  </indexterm>

	  <listitem>

	  <para>Extracts <replaceable>$substring</replaceable>
	    at <emphasis>end</emphasis> of <replaceable>$string</replaceable>,
	    where <replaceable>$substring</replaceable> is a regular
	    expression.</para>

	    <para>
	    <programlisting>stringZ=abcABC123ABCabc
#                ======

echo `expr match "$stringZ" '.*\([A-C][A-C][A-C][a-c]*\)'`    # ABCabc
echo `expr "$stringZ" : '.*\(......\)'`                       # ABCabc</programlisting>

	    </para>
	  </listitem>
	</varlistentry>

      </variablelist>

      <variablelist id="substringremoval">
        <title>Substring Removal</title>
	
	<varlistentry>
	  <term>${string#substring}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>removal</secondary>
	  </indexterm>

	  <listitem>
	  <para>Strips shortest match of
	    <replaceable>$substring</replaceable> from
	    <emphasis>front</emphasis> of
	    <replaceable>$string</replaceable>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string##substring}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>removal</secondary>
	  </indexterm>

	  <listitem>

	  <para>Strips longest match of
	    <replaceable>$substring</replaceable> from
	    <emphasis>front</emphasis> of
	    <replaceable>$string</replaceable>.</para>

	  <para>  
	  <programlisting>stringZ=abcABC123ABCabc
#       |----|
#       |----------|

echo ${stringZ#a*C}      # 123ABCabc
# Strip out shortest match between 'a' and 'C'.

echo ${stringZ##a*C}     # abc
# Strip out longest match between 'a' and 'C'.</programlisting>
	  </para>  
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string%substring}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>removal</secondary>
	  </indexterm>

	  <listitem>
	  <para>Strips shortest match of
	    <replaceable>$substring</replaceable> from
	    <emphasis>back</emphasis> of
	    <replaceable>$string</replaceable>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string%%substring}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>removal</secondary>
	  </indexterm>

	  <listitem>

	  <para>Strips longest match of
	    <replaceable>$substring</replaceable> from
	    <emphasis>back</emphasis> of
	    <replaceable>$string</replaceable>.</para>

	  <para>  
	  <programlisting>stringZ=abcABC123ABCabc
#                    ||
#        |------------|

echo ${stringZ%b*c}      # abcABC123ABCa
# Strip out shortest match between 'b' and 'c', from back of $stringZ.

echo ${stringZ%%b*c}     # a
# Strip out longest match between 'b' and 'c', from back of $stringZ.</programlisting>
	  </para>  

	    <example id="cvt">
	      <title>Converting graphic file formats, with filename change</title>
	      <programlisting>&cvt;</programlisting>
	    </example>


	  </listitem>
	</varlistentry>

      </variablelist>

      <variablelist id="substringreplacement">
        <title>Substring Replacement</title>

	<varlistentry>
	  <term>${string/substring/replacement}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>replacement</secondary>
	  </indexterm>

	  <listitem>
	  <para>Replace first match of
	    <replaceable>$substring</replaceable> with
	    <replaceable>$replacement</replaceable>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string//substring/replacement}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>replacement</secondary>
	  </indexterm>

	  <listitem>

	  <para>Replace all matches of
	    <replaceable>$substring</replaceable> with
	    <replaceable>$replacement</replaceable>.</para>

	  <para>  
	  <programlisting>stringZ=abcABC123ABCabc

echo ${stringZ/abc/xyz}           # xyzABC123ABCabc
                                  # Replaces first match of 'abc' with 'xyz'.

echo ${stringZ//abc/xyz}          # xyzABC123ABCxyz
                                  # Replaces all matches of 'abc' with # 'xyz'.</programlisting>
	  </para>  

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string/#substring/replacement}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>replacement</secondary>
	  </indexterm>

	  <listitem>
	  <para>If <replaceable>$substring</replaceable> matches
	    <emphasis>front</emphasis> end of
	    <replaceable>$string</replaceable>, substitute
	    <replaceable>$replacement</replaceable> for
	    <replaceable>$substring</replaceable>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>${string/%substring/replacement}</term>
	  <indexterm>
	    <primary>substring</primary>
	    <secondary>replacement</secondary>
	  </indexterm>

	  <listitem>

	  <para>If <replaceable>$substring</replaceable> matches
	    <emphasis>back</emphasis> end of
	    <replaceable>$string</replaceable>, substitute
	    <replaceable>$replacement</replaceable> for
	    <replaceable>$substring</replaceable>.</para>

	  <para>  
          <programlisting>stringZ=abcABC123ABCabc

echo ${stringZ/#abc/XYZ}          # XYZABC123ABCabc
                                  # Replaces front-end match of 'abc' with 'XYZ'.

echo ${stringZ/%abc/XYZ}          # abcABC123ABCXYZ
                                  # Replaces back-end match of 'abc' with 'XYZ'.</programlisting>
	  </para>  

	  </listitem>
	</varlistentry>

      </variablelist>

    <sect2 id="awkstringmanip">
      <title>Manipulating strings using awk</title>

          <para>A Bash script may invoke the string manipulation facilities of
	    <link linkend="awkref">awk</link> as an alternative to using its
	    built-in operations.</para>

	    <example id="substringex">
	      <title>Alternate ways of extracting substrings</title>
	      <programlisting>&substringex;</programlisting>
	    </example>

    </sect2> <!-- Manipulating strings using awk -->



    <sect2 id="strfdisc">
      <title>Further Discussion</title>
   
     <para>For more on string manipulation in scripts, refer to <xref
       linkend="Parameter-Substitution"> and the
       <link linkend="expextrsub">relevant section</link> of the <link
       linkend="exprref">expr</link> command listing. For script examples,
       see: <orderedlist>
         <listitem><para><xref linkend="ex45"></para></listitem>
	 <listitem><para><xref linkend="length"></para></listitem>
	 <listitem><para><xref linkend="pattmatching"></para></listitem>
         <listitem><para><xref linkend="rfe"></para></listitem>
         <listitem><para><xref linkend="varmatch"></para></listitem>
       </orderedlist>
      </para>	 

    </sect2> <!-- Further Discussion -->
    


    </sect1> <!-- Manipulating Strings -->



    <sect1 id="Parameter-Substitution">
      <title>Parameter Substitution</title>

            <para><anchor id="paramsubref"></para> 

            <variablelist id="pssub">
	      <title><anchor id="pssub1">Manipulating and/or expanding variables</title>
	      <varlistentry>
		<term>
		  <userinput>${parameter}</userinput></term>
		<listitem>

		<para>Same as <replaceable>$parameter</replaceable>, i.e.,
		  value of the variable
		  <replaceable>parameter</replaceable>.
		  In certain contexts, only the less ambiguous
		  <replaceable>${parameter}</replaceable> form
		  works.</para>

		<para>May be used for concatenating variables with strings.</para>

	        <para><programlisting>
your_id=${USER}-on-${HOSTNAME}
echo "$your_id"
#
echo "Old \$PATH = $PATH"
PATH=${PATH}:/opt/bin  #Add /opt/bin to $PATH for duration of script.
echo "New \$PATH = $PATH"
</programlisting></para>
		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>${parameter-default}</userinput></term>
		<term><userinput>${parameter:-default}</userinput></term>
		<listitem>
		<para>If parameter not set, use default.</para>
		<para><programlisting>
echo ${username-`whoami`}
# Echoes the result of `whoami`, if variable $username is still unset.</programlisting></para>

		<note><para><replaceable>${parameter-default}</replaceable>
		  and <replaceable>${parameter:-default}</replaceable>
		  are almost equivalent. The extra <token>:</token> makes
		  a difference only when <emphasis>parameter</emphasis>
		  has been declared, but is null.  </para></note>

		<para><programlisting>&paramsub;</programlisting></para>

		<para>The <emphasis>default parameter</emphasis> construct
		  finds use in providing <quote>missing</quote> command-line
		  arguments in scripts.</para>

		<para>
		  <programlisting>DEFAULT_FILENAME=generic.data
filename=${1:-$DEFAULT_FILENAME}
#  If not otherwise specified, the following command block operates
#+ on the file "generic.data".
#
#  Commands follow.</programlisting>
		</para>

		<para>See also <xref linkend="ex58">, <xref
		  linkend="ex73">, and <xref linkend="collatz">.</para>

                <para>Compare this method with <link
		  linkend="anddefault">using an <emphasis>and
		  list</emphasis> to supply a default command-line
		  argument</link>.</para>

		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>${parameter=default}</userinput></term>
		<term><userinput>${parameter:=default}</userinput></term>
		<listitem>
		<para><anchor id="defparam"></para>
		<para>If parameter not set, set it to default.</para>

		<para>Both forms nearly equivalent. The <token>:</token>
		  makes a difference only when <emphasis>$parameter</emphasis>
		  has been declared and is null,
		    <footnote>
		    <para>If $parameter is null in a
		      non-interactive script, it will terminate with a <link
		      linkend="exitcodesref"><returnvalue>127</returnvalue>
		      exit status</link> (the Bash error code code for
		      <quote>command not found</quote>).</para>
		      </footnote>
		  as above.
		    </para>

		<para><programlisting>
echo ${username=`whoami`}
# Variable "username" is now set to `whoami`.</programlisting></para>
	      </listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>${parameter+alt_value}</userinput></term>
		<term><userinput>${parameter:+alt_value}</userinput></term>
		<listitem>
		  <para>If parameter set, use
		    <userinput>alt_value</userinput>, else use null
		    string.</para>

		  <para>Both forms nearly equivalent. The <token>:</token>
		    makes a difference only when <emphasis>parameter</emphasis>
		    has been declared and is null, see below.</para>

		  <para><programlisting>echo "###### \${parameter+alt_value} ########"
echo

a=${param1+xyz}
echo "a = $a"      # a =

param2=
a=${param2+xyz}
echo "a = $a"      # a = xyz

param3=123
a=${param3+xyz}
echo "a = $a"      # a = xyz

echo
echo "###### \${parameter:+alt_value} ########"
echo

a=${param4:+xyz}
echo "a = $a"      # a =

param5=
a=${param5:+xyz}
echo "a = $a"      # a =
# Different result from   a=${param5+xyz}

param6=123
a=${param6+xyz}
echo "a = $a"      # a = xyz</programlisting></para>

		</listitem>
	      </varlistentry>
	      <varlistentry>
		<term><anchor id="qerrmsg"><userinput>${parameter?err_msg}</userinput></term>
		<term><userinput>${parameter:?err_msg}</userinput></term>
		<listitem><para>If parameter set, use it, else print err_msg.</para>
		<para>Both forms nearly equivalent. The <token>:</token>
		  makes a difference only when <emphasis>parameter</emphasis>
		  has been declared and is null, as above.</para>
		</listitem>
	      </varlistentry>
	    </variablelist>

	    <example id="ex6">
	      <title>Using parameter substitution and error messages</title>
	      <programlisting>&ex6;</programlisting>
	    </example>

	    <example id="usagemessage">
	      <title>Parameter substitution and <quote>usage</quote> messages</title>
	      <programlisting>&usagemessage;</programlisting>
	    </example>

	    
	    
            <formalpara><title>Parameter substitution and/or expansion</title>
	      
	      <para><anchor id="psub2">The following expressions are
		the complement to the <command>match</command>
		<replaceable>in</replaceable> <command>expr</command>
		string operations (see <xref linkend="ex45">).
		These particular ones are used mostly in parsing file
		path names.</para></formalpara>

	    <variablelist id="psorex">
              <title><anchor id="psorex1">Variable length / Substring removal</title>

	      <varlistentry>

		<term><userinput>${#var}</userinput></term>
		<listitem>
		  <para><userinput>String length</userinput> (number
		    of characters in <varname>$var</varname>). For
		    an <link linkend="arrayref">array</link>,
		    <command>${#array}</command> is the length of the
		    first element in the array.</para>

		  <note><para>
		    Exceptions:

		  <itemizedlist>
		    <listitem><para>
		      <command>${#*}</command> and
		      <command>${#@}</command> give the <emphasis>number
		      of positional parameters</emphasis>.
		    </para></listitem>
		  
		    <listitem><para>
		      For an array, <command>${#array[*]}</command> and
		      <command>${#array[@]}</command> give the number
		      of elements in the array.
		    </para></listitem>
		  </itemizedlist>
		  </para></note>

	      <example id="length">
	        <title>Length of a variable</title>
	        <programlisting>&length;</programlisting>
	      </example>	    

		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>${var#Pattern}</userinput></term>
		<term><userinput>${var##Pattern}</userinput></term>

		<listitem>
		<para>Remove from <varname>$var</varname>
		  the shortest/longest part of <varname>$Pattern</varname>
		  that matches the <replaceable>front end</replaceable>
		  of <varname>$var</varname>.
		</para>
		  
		<para>A usage illustration from <xref linkend="daysbetween">:
<programlisting># Function from "days-between.sh" example.
# Strips leading zero(s) from argument passed.

strip_leading_zero () # Better to strip possible leading zero(s)
{                     # from day and/or month
  val=${1#0}          # since otherwise Bash will interpret them
  return $val         # as octal values (POSIX.2, sect 2.9.2.1).
}</programlisting>
		</para>


		<para>Another usage illustration: 
<programlisting>echo `basename $PWD`        # Basename of current working directory.
echo "${PWD##*/}"           # Basename of current working directory.
echo
echo `basename $0`          # Name of script.
echo $0                     # Name of script.
echo "${0##*/}"             # Name of script.
echo
filename=test.data
echo "${filename##*.}"      # data
                            # Extension of filename.</programlisting>
		</para>
		  
		  </listitem>

	      </varlistentry>
	      
	      <varlistentry>
		<term><anchor id="pctpatref"><userinput>${var%Pattern}</userinput></term>
		<term><userinput>${var%%Pattern}</userinput></term>

		<listitem><para>Remove from <varname>$var</varname>
		  the shortest/longest part of <varname>$Pattern</varname>
		  that matches the <replaceable>back end</replaceable>
		  of <varname>$var</varname>.
		  </para></listitem>

	      </varlistentry>
	    </variablelist>
	    
	    <para><link linkend="bash2ref">Version 2</link> of Bash adds
	      additional options.</para>

	    <example id="pattmatching">
	      <title>Pattern matching in parameter substitution</title>
	      <programlisting>&pattmatching;</programlisting>
	    </example>


	    <example id="rfe">
	      <title>Renaming file extensions<token>:</token></title>
	      <programlisting>&rfe;</programlisting>
	    </example>

	    
	    <variablelist id="exprepl">
	      <title><anchor id="exprepl1">Variable expansion / Substring
	      replacement</title>
	      
	      <varlistentry>
	      <term></term>
	      <listitem>
	        <para>These constructs have been adopted from
		  <emphasis>ksh</emphasis>.</para>
	      </listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>${var:pos}</userinput></term>
		<listitem>
		  <para>Variable <replaceable>var</replaceable> expanded,
		    starting from offset <replaceable>pos</replaceable>.
		  </para>
		  </listitem>
	      </varlistentry>
	      
	      <varlistentry>
		<term><userinput>${var:pos:len}</userinput></term>
		<listitem>
		  <para>Expansion to a max of <replaceable>len</replaceable>
		    characters of variable <replaceable>var</replaceable>, from offset
		    <replaceable>pos</replaceable>. See <xref linkend="pw">
		    for an example of the creative use of this operator.
		  </para>
		  </listitem>
	      </varlistentry>
	      
	      <varlistentry>
		<term><userinput>${var/Pattern/Replacement}</userinput></term>
		<listitem>
		  <para>First match of <replaceable>Pattern</replaceable>,
		    within <replaceable>var</replaceable> replaced with
		    <replaceable>Replacement</replaceable>.</para>
		  <para>If <replaceable>Replacement</replaceable> is
		    omitted, then the first match of
		    <replaceable>Pattern</replaceable> is replaced by
		    <emphasis>nothing</emphasis>, that is, deleted.</para>
		  </listitem>  
	      </varlistentry>
	      
	      <varlistentry>
		<term><userinput>${var//Pattern/Replacement}</userinput></term>
		<listitem>

                  <formalpara><title>Global replacement</title>
		  <para>All matches of <replaceable>Pattern</replaceable>,
		    within <replaceable>var</replaceable> replaced with
		    <replaceable>Replacement</replaceable>.</para>
		    </formalpara>

		  <para>As above, if <replaceable>Replacement</replaceable>
		    is omitted, then all occurrences of
		    <replaceable>Pattern</replaceable> are replaced by
		    <emphasis>nothing</emphasis>, that is, deleted.</para>
	    
	    <example id="ex7">
	      <title>Using pattern matching to parse arbitrary strings</title>
	      <programlisting>&ex7;</programlisting>
	    </example>

		  </listitem>
	      </varlistentry>	

	      <varlistentry>
		<term><userinput>${var/#Pattern/Replacement}</userinput></term>
		<listitem>
		  <para>If <emphasis>prefix</emphasis> of
		  <replaceable>var</replaceable> matches
		  <replaceable>Pattern</replaceable>, then substitute
		  <replaceable>Replacement</replaceable> for
		  <replaceable>Pattern</replaceable>.</para>
		</listitem>
	      </varlistentry>	

	      <varlistentry>
		<term><userinput>${var/%Pattern/Replacement}</userinput></term>
		<listitem>
		  <para>If <emphasis>suffix</emphasis> of
		  <replaceable>var</replaceable> matches
		  <replaceable>Pattern</replaceable>, then substitute
		  <replaceable>Replacement</replaceable> for
		  <replaceable>Pattern</replaceable>.</para>

	    <example id="varmatch">
	      <title>Matching patterns at prefix or suffix of string</title>
	      <programlisting>&varmatch;</programlisting>
	    </example>

		</listitem>
	      </varlistentry>	

	      <varlistentry>
		<term><userinput>${!varprefix*}</userinput></term>
		<term><userinput>${!varprefix@}</userinput></term>
		<listitem>
		  <para>Matches all previously declared variables beginning
		    with <emphasis>varprefix</emphasis>.
		      <programlisting>xyz23=whatever
xyz24=

a=${!xyz*}      # Expands to names of declared variables beginning with "xyz".
echo "a = $a"   # a = xyz23 xyz24
a=${!xyz@}      # Same as above.
echo "a = $a"   # a = xyz23 xyz24

# Bash, version 2.04, adds this feature.</programlisting>
                  </para>

		  </listitem>
	      </varlistentry>	

	    </variablelist>

    </sect1> <!-- Parameter Substitution -->  


      <sect1 id="declareref">
	<indexterm>
	  <primary>declare</primary>
	</indexterm>
	<indexterm>
	  <primary>typeset</primary>
	</indexterm>
	<indexterm>
	  <primary>command</primary>
	  <secondary>declare</secondary>
	</indexterm>
	<indexterm>
	  <primary>command</primary>
	  <secondary>typeset</secondary>
	</indexterm>
	<title>Typing variables: <command>declare</command> or
	  <command>typeset</command></title>
	
	<para>The <command>declare</command> or <command>typeset</command>
	  <link linkend="builtinref">builtins</link> (they are exact
	  synonyms) permit restricting the properties of variables. This
	  is a very weak form of the typing available in certain
	  programming languages. The <command>declare</command>
	  command is specific to version 2 or later of Bash. The
	  <command>typeset</command> command also works in ksh
	  scripts.</para>

	<variablelist id="declareopsref">
	  <title><anchor id="declareopsref1">declare/typeset options</title>

	  <varlistentry>
	    <term><token>-r</token> <replaceable>readonly</replaceable></term>
	    <listitem><para><programlisting>declare -r var1</programlisting></para>
	      <para>(<userinput>declare -r var1</userinput> works the same as
		<userinput>readonly var1</userinput>)</para>
	      <para>This is the rough equivalent of the C
		<command>const</command> type qualifier. An 
		attempt to change the value of a readonly variable fails with an 
		error message.</para></listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-i</token> <replaceable>integer</replaceable></term>

	    <listitem>

	      <para><programlisting>declare -i number
# The script will treat subsequent occurrences of "number" as an integer.		

number=3
echo "Number = $number"     # Number = 3

number=three
echo "Number = $number"     # Number = 0
# Tries to evaluate the string "three" as an integer.</programlisting></para>
		
              <para>Certain arithmetic operations are permitted
		for declared integer variables without the need
		for <link linkend="exprref">expr</link> or <link
		linkend="letref">let</link>.</para>

              <para><programlisting>n=6/3
echo "n = $n"       # n = 6/3

declare -i n
n=6/3
echo "n = $n"       # n = 2</programlisting></para>
		
		</listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-a</token> <replaceable>array</replaceable></term>
	    <listitem><para><programlisting>declare -a indices</programlisting></para>
	      <para>The variable <varname>indices</varname> will be treated as
		an array.</para></listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><token>-f</token> <replaceable>functions</replaceable></term>
	    <listitem>

	      <para><programlisting>declare -f</programlisting></para>
	      <para>A <userinput>declare -f</userinput> line with no
		arguments in a script causes a listing of all the
		functions previously defined in that script.</para>

	      <para><programlisting>declare -f function_name</programlisting></para>
	      <para>A <userinput>declare -f function_name</userinput>
		in a script lists just the function named.</para>

            </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term><token>-x</token> <link linkend="exportref">export</link></term>
	      <listitem><para><programlisting>declare -x var3</programlisting></para>
	      <para>This declares a variable as available for exporting outside the
		environment of the script itself.</para></listitem>
	  </varlistentry>

	  <varlistentry>
	    <term>var=$value</term>
	      <listitem>
	        <para><programlisting>declare -x var3=373</programlisting></para>
		<para>The <command>declare</command> command permits
		  assigning a value to a variable in the same statement
		  as setting its properties.</para>
	      </listitem>
	  </varlistentry>
	      

	</variablelist>

	<example id="ex20">
	  <title>Using <command>declare</command> to type variables</title>
	  <programlisting>&ex20;</programlisting>
	</example>

      </sect1> <!-- Typing variables: declare or typeset -->


      <sect1 id="ivr">
        <title>Indirect References to Variables</title>

	<para><anchor id="ivrref"></para>

	<para>Assume that the value of a variable is the name of a second
	  variable.  Is it somehow possible to retrieve the value
	  of this second variable from the first one? For example,
	  if <replaceable>a=letter_of_alphabet</replaceable>
	  and <replaceable>letter_of_alphabet=z</replaceable>,
	  can a reference to <replaceable>a</replaceable> return
	  <replaceable>z</replaceable>? This can indeed be done, and
	  it is called an <emphasis>indirect reference</emphasis>. It
	  uses the unusual <replaceable>eval var1=\$$var2</replaceable>
	  notation.</para>

      <example id="indref">
	<title>Indirect References</title>
	<programlisting>&indref;</programlisting>
      </example>

      <example id="coltotaler2">
	<title>Passing an indirect reference to <replaceable>awk</replaceable></title>
	<programlisting>&coltotaler2;</programlisting>
      </example>

      <caution><para>This method of indirect referencing is a bit tricky.
	If the second order variable changes its value, then the first
	order variable must be properly dereferenced (as in the above
	example). <anchor id="ivr2">Fortunately, the
	<replaceable>${!variable}</replaceable> notation introduced
	with <link linkend="bash2ref">version 2</link> of Bash
	(see <xref linkend="ex78">) makes indirect referencing more
	intuitive.</para></caution>

      </sect1> <!-- Indirect References to Variables -->


      <sect1 id="randomvar">

	<indexterm>
	  <primary>$RANDOM</primary>
	</indexterm>
	<indexterm>
	  <primary>variable</primary>
	  <secondary>$RANDOM</secondary>
	</indexterm>
	<title>$RANDOM: generate random integer</title>
	<para>$RANDOM is an internal Bash function (not a constant) that
	  returns a <emphasis>pseudorandom</emphasis> integer in the range
	  0 - 32767. $RANDOM should <replaceable>not</replaceable> be used
	  to generate an encryption key.</para>

	<example id="ex21">
	  <title>Generating random numbers</title>
	  <programlisting>&ex21;</programlisting>
	</example>

	<example id="pickcard">
	  <title>Picking a random card from a deck</title>
	  <programlisting>&pickcard;</programlisting>
	</example>


	<note>

	<para>
	<emphasis>Jipe</emphasis> points out another set of techniques
	for generating random numbers within a range.
	</para>

	<para>
	<programlisting>#  Generate random number between 6 and 30.
rnumber=$((RANDOM%25+6))	

#  Generate random number in the same 6 - 30 range,
#+ but the number must be evenly divisible by 3.
rnumber=$(((RANDOM%30/3+1)*3))

#  Exercise: Try to figure out the pattern here.</programlisting>
	</para>

	</note>


	<para>Just how random is $RANDOM? The best way to test this is
	  to write a script that tracks the distribution of
	  <quote>random</quote> numbers generated by $RANDOM. Let's roll
	  a $RANDOM die a few times...</para>

	<example id="randomtest">
	  <title>Rolling the die with RANDOM</title>
	  <programlisting>&randomtest;</programlisting>
	</example>

	<para>As we have seen in the last example, it is best to
	  <quote>reseed</quote> the <varname>RANDOM</varname>
	  generator each time it is invoked. Using the same seed
	  for <varname>RANDOM</varname> repeats the same series
	  of numbers.  (This mirrors the behavior of the
	  <replaceable>random()</replaceable> function in C.)</para>

	<example id="seedingrandom">
	  <title>Reseeding RANDOM</title>
	  <programlisting>&seedingrandom;</programlisting>
	</example>

	<para><anchor id="urandomref"></para>
	<note>
	<para>The <filename>/dev/urandom</filename> device-file provides
	  a means of generating much more <quote>random</quote>
	  pseudorandom numbers than the <varname>$RANDOM</varname>
	  variable.  <userinput>dd if=/dev/urandom of=targetfile
	  bs=1 count=XX</userinput> creates a file of well-scattered
	  pseudorandom numbers.  However, assigning these numbers
	  to a variable in a script requires a workaround, such as
	  filtering through <link linkend="odref">od</link> (as in
	  above example) or using <link linkend="ddref">dd</link>
	  (see <xref linkend="blotout">).</para>

        <para><anchor id="awkrandomref"></para>
	  
        <para>There are also other means of generating pseudorandom
          numbers in a script. <command>Awk</command> provides a
	  convenient means of doing this.</para>

	    <example id="random2">
	      <title>Pseudorandom numbers, using <link
	        linkend="awkref">awk</link></title>
	      <programlisting>&random2;</programlisting>
	    </example>

	  </note>



      </sect1> <!-- RANDOM: generate random integer -->


      <sect1 id="dblparens">
        <title>The Double Parentheses Construct</title>

	<para>Similar to the <link linkend="letref">let</link> command,
	  the <command>((...))</command> construct permits arithmetic
	  expansion and evaluation. In its simplest form, <userinput>a=$((
	  5 + 3 ))</userinput> would set <quote>a</quote> to <quote>5 +
	  3</quote>, or 8. However, this double parentheses construct is
	  also a mechanism for allowing C-type manipulation of variables
	  in Bash.</para>

      <example id="cvars">
	<title>C-type manipulation of variables</title>
	<programlisting>&cvars;</programlisting>
      </example>

        <para>See also <xref linkend="forloopc">.</para>


      </sect1> <!-- The Double Parentheses Construct  -->
      

  </chapter> <!-- Variables Revisited -->


  <chapter id="loops">
    <title>Loops and Branches</title>


      <para>Operations on code blocks are the key to structured, organized
        shell scripts. Looping and branching constructs provide the tools for
	accomplishing this.</para>

      <sect1 id="loops1">
        <title>Loops</title>

      <para>A <emphasis>loop</emphasis> is a block of code that iterates
        (repeats) a list of commands as long as the loop control condition is
	true.</para>


      <variablelist id="forloopref">
        <title><anchor id="forloopref1">for loops</title>

	<varlistentry>
	  <term><command>for (in)</command></term>
	  <indexterm>
	    <primary>for</primary>
	  </indexterm>
	  <indexterm>
	    <primary>in</primary>
	  </indexterm>
	  <indexterm>
	    <primary>do</primary>
	  </indexterm>
	  <indexterm>
	    <primary>done</primary>
	  </indexterm>
	  <indexterm>
	    <primary>loop</primary>
	    <secondary>for</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is the basic looping construct. It differs significantly
	      from its C counterpart.</para>

	    <para><cmdsynopsis>
		<command>for</command>
		<arg choice="plain"><replaceable>arg</replaceable></arg>
		<arg choice="plain">in</arg>
		<arg choice="opt"><replaceable>list</replaceable></arg><sbr>
		<arg choice="plain">do</arg><sbr>
		<arg rep=repeat choice=plain><replaceable>&nbsp;command(s)</replaceable></arg><sbr>
		<arg choice="plain">done</arg>
	      </cmdsynopsis></para>

            <note><para>During each pass through the loop,
	      <replaceable>arg</replaceable> takes on the
	      value of each successive variable in the
	      <replaceable>list</replaceable>.</para></note>

	    <para><programlisting>for arg in "$var1" "$var2" "$var3" ... "$varN"  
# In pass 1 of the loop, $arg = $var1	    
# In pass 2 of the loop, $arg = $var2	    
# In pass 3 of the loop, $arg = $var3	    
# ...
# In pass N of the loop, $arg = $varN

# Arguments in [list] quoted to prevent possible word splitting.</programlisting></para>

	    
	    <para>The argument <replaceable>list</replaceable> may contain wild cards.</para>

	    <para>If <command>do</command> is on same line as
	      <command>for</command>, there needs to be a semicolon
	      after list.</para>

	    <para><cmdsynopsis>
		<command>for</command>
		<arg choice="plain"><replaceable>arg</replaceable></arg>
		<arg choice="plain">in</arg>
		<arg choice="opt"><replaceable>list</replaceable></arg>
		<arg choice="plain">;</arg>
		<arg choice="plain">do</arg><sbr>
	      </cmdsynopsis></para>

	    <example id="ex22">
	      <title>Simple <command>for</command> loops</title>
	      <programlisting>&ex22;</programlisting>
	    </example>

            
	    <note><para>Each <userinput>[list]</userinput> element
	      may contain multiple parameters. This is useful when
	      processing parameters in groups. In such cases, use the
	      <command>set</command> command (see <xref linkend="ex34">)
	      to force parsing of each <userinput>[list]</userinput>
	      element and assignment of each component to the positional
	      parameters.</para></note>

	    <example id="ex22a">
	      <title><command>for</command> loop with two parameters in each
	      [list] element</title>
	      <programlisting>&ex22a;</programlisting>
	    </example>


	    <para>A variable may supply the <userinput>[list]</userinput> in a
	      <command>for</command> loop.</para>

	    <example id="fileinfo">
	      <title><emphasis>Fileinfo:</emphasis> operating on a file list
	        contained in a variable</title>
	      <programlisting>&fileinfo;</programlisting>
	    </example>

	    
	    <para>The <userinput>[list]</userinput> in a
	      <command>for</command> loop may contain filename <link
	      linkend="globbingref">globbing</link>, that is, using
	      wildcards for filename expansion.</para>

	    <example id="listglob">
	      <title><command>Operating on files with a for</command> loop</title>
	      <programlisting>&listglob;</programlisting>
	    </example>


	    <para>Omitting the <userinput>in [list]</userinput> part of a
	      <command>for</command> loop causes the loop to operate
	      on <token>$@</token>, the list of arguments given
	      on the command line to the script. A particularly clever
	      illustration of this is <xref linkend="primes">.</para>

	    <example id="ex23">
	      <title>Missing <userinput>in [list]</userinput> in a
		<command>for</command> loop</title>
	      <programlisting>&ex23;</programlisting>
	    </example>


	    <para>It is possible to use <link
	      linkend="commandsubref">command substitution</link>
	      to generate the <userinput>[list]</userinput> in a
	      <command>for</command> loop. See also <xref linkend="ex53">,
	      <xref linkend="symlinks"> and <xref linkend="base">.</para>

	    <example id="forloopcmd">
	      <title>Generating the [list] in a <command>for</command>
	        loop with command substitution</title>
	      <programlisting>&forloopcmd;</programlisting>
	    </example>


	    <para>This is a somewhat more complex example of using command
	      substitution to create the [list].</para>

	    <example id="bingrep">
	      <title>A <link linkend="grepref">grep</link> replacement
	        for binary files</title>
	      <programlisting>&bingrep;</programlisting>
	    </example>

	    <para>More of the same.</para>

	    <example id="userlist">
	      <title>Listing all users on the system</title>
	      <programlisting>&userlist;</programlisting>
	    </example>

	    <para>A final example of the [list] resulting from command
	      substitution.</para>

	    <example id="findstring">
	      <title>Checking all the binaries in a directory for
	      authorship</title>
	      <programlisting>&findstring;</programlisting>
	    </example>


	    <para>The output of a <command>for</command> loop may be piped to
	      a command or commands.</para>

	    <example id="symlinks">
	      <title>Listing the symbolic links in a directory</title>
	      <programlisting>&symlinks;</programlisting>
	    </example>

	    <para>The <filename>stdout</filename> of a loop may be <link
	      linkend="ioredirref">redirected</link> to a file, as this slight
	      modification to the previous example shows.</para>

	    <example id="symlinks2">
	      <title>Symbolic links in a directory, saved to a file</title>
	      <programlisting>&symlinks2;</programlisting>
	    </example>

	    <para>There is an alternative syntax to a <command>for</command>
	      loop that will look very familiar to C programmers. This
	      requires double parentheses.</para>

	    <example id="forloopc">
	      <title>A C-like <command>for</command> loop</title>
	      <programlisting>&forloopc;</programlisting>
	    </example>

	    <para>See also <xref linkend="qfunction">, <xref
	      linkend="twodim">, and <xref linkend="collatz">.</para>

	    <para>---</para>

	    <para>Now, a <emphasis>for-loop</emphasis> used in a
	      <quote>real-life</quote> context.</para>

	    <example id="ex24">
	      <title>Using <command>efax</command> in batch mode</title>
	      <programlisting>&ex24;</programlisting>
	    </example>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="whileloopref"><command>while</command></term>
	  <indexterm>
	    <primary>while</primary>
	  </indexterm>
	  <indexterm>
	    <primary>do</primary>
	  </indexterm>
	  <indexterm>
	    <primary>done</primary>
	  </indexterm>
	  <indexterm>
	    <primary>loop</primary>
	    <secondary>while</secondary>
	  </indexterm>
	  <listitem>
	    <para>This construct tests for a condition at the top of a
	      loop, and keeps looping as long as that condition
	      is true (returns a <returnvalue>0</returnvalue> <link
	      linkend="exitstatusref">exit status</link>).  In contrast
	      to a <link linkend="forloopref1">for loop</link>, a
	      <emphasis>while loop</emphasis> finds use in situations
	      where the number of loop repetitions is not known
	      beforehand.</para>

	    <para><cmdsynopsis>
		<command>while</command>
		<arg choice="opt"><replaceable>condition</replaceable></arg><sbr>
		<arg choice="plain">do</arg><sbr>
		<arg choice="plain" rep="repeat"><replaceable>&nbsp;command</replaceable></arg><sbr>
		<arg choice="plain">done</arg>
	      </cmdsynopsis></para>


	    <para>As is the case with <token>for/in</token> loops, placing the
	      <command>do</command> on the same line as the condition test
	      requires a semicolon.</para>

	    <para><cmdsynopsis>
		<command>while</command>
		<arg choice="opt"><replaceable>condition</replaceable></arg>
		<arg choice="plain">;</arg>
		<arg choice="plain">do</arg>
	      </cmdsynopsis></para>
	    
	    <para>Note that certain specialized <command>while</command>
	      loops, as, for example,  a <link
	      linkend="getoptsx">getopts construct</link>, deviate
	      somewhat from the standard template given here.</para>

	    <example id="ex25">
	      <title>Simple <command>while</command> loop</title>
	      <programlisting>&ex25;</programlisting>
	    </example>
	    
	    <example id="ex26">
	      <title>Another <command>while</command> loop</title>
	      <programlisting>&ex26;</programlisting>
	    </example>	    


            <para>A <command>while</command> loop may have multiple
	      conditions. Only the final condition determines when the loop
	      terminates. This necessitates a slightly different loop syntax,
	      however.</para>

	    <example id="ex26a">
	      <title><command>while</command> loop with multiple conditions</title>
	      <programlisting>&ex26a;</programlisting>
	    </example>	    

	    <para>As with a <command>for</command> loop, a
	      <command>while</command> loop may employ C-like syntax
	      by using the double parentheses construct (see also <xref
	      linkend="cvars">).</para>

	    <example id="whloopc">
	      <title>C-like syntax in a <command>while</command> loop</title>
	      <programlisting>&whloopc;</programlisting>
	    </example>

	    <note><para>A <command>while</command> loop may have its
	      <filename>stdin</filename> <link
	      linkend="redirref">redirected to a file</link> by a
	      <token>&lt;</token> at its end.</para></note>

	    </listitem>
	  </varlistentry>



	<varlistentry>
	  <term><anchor id="untilloopref"><command>until</command></term>
	  <indexterm>
	    <primary>until</primary>
	  </indexterm>
	  <indexterm>
	    <primary>do</primary>
	  </indexterm>
	  <indexterm>
	    <primary>done</primary>
	  </indexterm>
	  <indexterm>
	    <primary>loop</primary>
	    <secondary>until</secondary>
	  </indexterm>

	  <listitem>
	    <para>This construct tests for a condition at the top of a loop, and keeps
	      looping as long as that condition is false (opposite of
	      <command>while</command> loop).</para>

	    <para><cmdsynopsis>
		<command>until</command>
		<arg choice="opt"><replaceable>condition-is-true</replaceable></arg><sbr>
		<arg choice="plain">do</arg><sbr>
		<arg choice="plain" rep="repeat"><replaceable>&nbsp;command</replaceable></arg><sbr>
		<arg choice="plain">done</arg>
	      </cmdsynopsis></para>

	    <para>Note that an <command>until</command> loop tests for the
	      terminating condition at the top of the loop, differing from a
	      similar construct in some programming languages.</para>

	    <para>As is the case with <token>for/in</token> loops, placing the
	      <command>do</command> on the same line as the condition test
	      requires a semicolon.</para>

	    <para><cmdsynopsis>
		<command>until</command>
		<arg choice="opt"><replaceable>condition-is-true</replaceable></arg>
		<arg choice="plain">;</arg>
		<arg choice="plain">do</arg>
	      </cmdsynopsis></para>

	    <example id="ex27">
	      <title><command>until</command> loop</title>
	      <programlisting>&ex27;</programlisting>
	    </example>	    
	    </listitem>
	  </varlistentry>

	</variablelist>

    </sect1> <!-- Loops -->



      <sect1 id="nestedloops">
        <title>Nested Loops</title>

	<para>A nested loop is a loop within a loop, an inner loop within the
	  body of an outer one. What happens is that the first pass of the
	  outer loop triggers the inner loop, which executes to completion.
	  Then the second pass of the outer loop triggers the inner loop
	  again. This repeats until the outer loop finishes. Of course, a
	  <command>break</command> within either the inner or outer loop may
	  interrupt this process.</para>

	    <example id="nestedloop">
	      <title>Nested Loop</title>
	      <programlisting>&nestedloop;</programlisting>
	    </example>	    

        <para>See <xref linkend="bubble"> for an illustration of nested
	  <quote>while</quote> loops, and <xref linkend="ex68"> to see a
	  <quote>while</quote> loop nested inside an <quote>until</quote>
	  loop.</para>

    </sect1> <!-- Nested Loops -->


      <sect1 id="loopcontrol">
        <title>Loop Control</title>

	<variablelist id="brkcont">
	  <title><anchor id="brkcont1">Commands Affecting Loop Behavior</title>

	<varlistentry>
	  <indexterm>
	    <primary>break</primary>
	  </indexterm>
	  <indexterm>
	    <primary>continue</primary>
	  </indexterm>
	  <indexterm>
	    <primary>loop</primary>
	    <secondary>break</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>loop</primary>
	    <secondary>continue</secondary>
	  </indexterm>
	  <term><command>break</command></term>
	  <term><command>continue</command></term>
	  <listitem>
	    <para>The <command>break</command> and <command>continue</command>
	      loop control commands
		<footnote><para>These are shell <link
		linkend="builtinref">builtins</link>,
		whereas other loop commands, such as <link
		linkend="whileloopref">while</link> and <link
		linkend="caseesac1">case</link>, are <link
		linkend="keywordref">keywords</link>.</para></footnote>
	      correspond exactly to their counterparts in other
	      programming languages. The <command>break</command>
	      command terminates the loop (breaks out of it), while
	      <command>continue</command> causes a jump to the next
	      iteration of the loop, skipping all the remaining commands
	      in that particular loop cycle.</para>

	    <example id="ex28">
	      <title>Effects of <command>break</command> and
		<command>continue</command> in a loop</title>
	      <programlisting>&ex28;</programlisting>
	    </example>	    

            <para>The <command>break</command> command may optionally take a
	      parameter. A plain <command>break</command> terminates
	      only the innermost loop in which it is embedded,
	      but a <command>break N</command> breaks out of
	      <parameter>N</parameter> levels of loop.</para>

	    <example id="breaklevels">
	      <title>Breaking out of multiple loop levels</title>
	      <programlisting>&breaklevels;</programlisting>
	    </example>	    

	    <para>The <command>continue</command> command, similar to
	      <command>break</command>, optionally takes a parameter. A
	      plain <command>continue</command> cuts short the
	      current iteration within its loop and begins the next.
	      A <command>continue N</command> terminates all remaining
	      iterations at its loop level and continues with the
	      next iteration at the loop <option>N</option> levels
	      above.</para>

	    <example id="continuelevels">
	      <title>Continuing at a higher loop level</title>
	      <programlisting>&continuelevels;</programlisting>
	    </example>	    

	    <example id="continuenex">
	      <title>Using <quote>continue N</quote> in an actual task</title>
	      <programlisting>&continuenex;</programlisting>
	    </example>	    

	    <caution><para>The <command>continue N</command> construct is
	      difficult to understand and tricky to use in any meaningful
	      context. It is probably best avoided.</para></caution>

	  </listitem>
	</varlistentry>

	</variablelist>

    </sect1> <!-- Loop Control Commands -->



      <sect1 id="testbranch">
        <title>Testing and Branching</title>

	<para>The <command>case</command> and <command>select</command>
	  constructs are technically not loops, since they do not iterate the
	  execution of a code block. Like loops, however, they direct
	  program flow according to conditions at the top or bottom of
	  the block.</para>

	<variablelist id="caseesac">
	  <title><anchor id="caseesac1">Controlling program flow in a code
	    block</title>

	<varlistentry>
	  <term><command>case (in) / esac</command></term>
	  <indexterm>
	    <primary>case</primary>
	  </indexterm>
	  <indexterm>
	    <primary>in</primary>
	  </indexterm>
	  <indexterm>
	    <primary>esac</primary>
	  </indexterm>
	  <indexterm>
	    <primary>switch</primary>
	  </indexterm>
	  <indexterm>
	    <primary>;;</primary>
	  </indexterm>
	  <indexterm>
	    <primary>menus</primary>
	  </indexterm>

	  <listitem>
	    <para>The <command>case</command> construct is the shell equivalent
	      of <command>switch</command>  in C/C++.
	      It permits branching to one of a number of code blocks, depending
	      on condition tests. It serves as a kind of shorthand for multiple
	      <token>if/then/else</token> statements and is an appropriate tool
	      for creating menus.</para>

	    <para><cmdsynopsis>
		<command>case</command>
		<arg choice="plain">"$<replaceable>variable</replaceable>"</arg>
		<arg choice="plain">in</arg><sbr><sbr>
		<arg choice="plain">&nbsp;"$<replaceable>condition1</replaceable>" )</arg><sbr>
		<arg choice="plain" rep="repeat">&nbsp;<replaceable>command</replaceable></arg><sbr>
		<arg choice="plain">&nbsp;;;</arg><sbr><sbr>
		<arg choice="plain">&nbsp;"$<replaceable>condition2</replaceable>" )</arg><sbr>
		<arg choice="plain" rep="repeat">&nbsp;<replaceable>command</replaceable></arg><sbr>
		<arg choice="plain">&nbsp;;;</arg><sbr><sbr>
		<arg choice="plain">esac</arg>
	      </cmdsynopsis></para>

	    <note><para>
	      <itemizedlist>
		<listitem><para>Quoting the variables is not mandatory, since
		word splitting does not take place.</para>
		</listitem>
		<listitem><para>Each test line ends with a right paren <token>)</token>.</para>
		</listitem>
		<listitem><para>Each condition block ends with a <emphasis>double</emphasis>
		    semicolon <token>;;</token>.</para>
		</listitem>
		<listitem><para>The entire <command>case</command> block terminates with an
	      <command>esac</command> (<wordasword>case</wordasword> spelled
		backwards).</para>
		  </listitem>
	      </itemizedlist>
	    </para></note>

	    <example id="ex29">
	      <title>Using <command>case</command></title>
	      <programlisting>&ex29;</programlisting>
	    </example>	    

	    <example id="ex30">
	      <title>Creating menus using <command>case</command></title>
	      <programlisting>&ex30;</programlisting>
	    </example>	    

	    <para>An exceptionally clever use of <command>case</command>
	      involves testing for command-line parameters.
	      <programlisting>#! /bin/bash

case "$1" in
"") echo "Usage: ${0##*/} &lt;filename&gt;"; exit 65;;  # No command-line parameters,
                                                  # or first parameter empty.
# Note that ${0##*/} is ${var##pattern} param substitution. Net result is $0.

-*) FILENAME=./$1;;   # If filename passed as argument ($1) starts with a dash,
                      # replace it with ./$1
                      # so further commands don't interpret it as an option.

* ) FILENAME=$1;;     # Otherwise, $1.
esac</programlisting></para>


	    <example id="casecmd">
	      <title>Using command substitution to generate the
	        <command>case</command> variable</title>
	      <programlisting>&casecmd;</programlisting>
	    </example>	    

	    <para>A <command>case</command> construct can filter strings for
	      <link linkend="globbingref">globbing</link> patterns.</para>

	    <example id="matchstring">
	      <title>Simple string matching</title>
	      <programlisting>&matchstring;</programlisting>
	    </example>	    

	    <example id="isalpha">
	      <title>Checking for alphabetic input</title>
	      <programlisting>&isalpha;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="selectref"><command>select</command></term>
	  <indexterm>
	    <primary>select</primary>
	  </indexterm>
	  <indexterm>
	    <primary>menus</primary>
	  </indexterm>
	  <listitem>
	    <para>The <command>select</command> construct, adopted from the Korn
	      Shell, is yet another tool for building menus.</para>

	    <para><cmdsynopsis>
		<command>select</command>
		<arg choice="plain"><replaceable>variable</replaceable></arg>
		<arg choice="opt">in <replaceable>list</replaceable></arg><sbr>
		<arg choice="plain">do</arg><sbr>
		<arg choice="plain" rep="repeat">&nbsp;<replaceable>command</replaceable></arg><sbr>
		<arg choice="plain">&nbsp;break</arg><sbr>
		<arg choice="plain">done</arg>
	      </cmdsynopsis></para>
	    
	    <para>This prompts the user to enter one of the choices presented in the
	      variable list.  Note that <command>select</command> uses the
	      <varname>PS3</varname> prompt (<prompt>#? </prompt>) by default, 
		but that this may be changed.</para>
	    
	    <example id="ex31">
	      <title>Creating menus using <command>select</command></title>
	      <programlisting>&ex31;</programlisting>
	    </example>	    

	    <para>If <userinput>in <replaceable>list</replaceable></userinput> is
	      omitted, then <command>select</command> uses the list of command
	      line arguments (<varname>$@</varname>) passed to the script or to
	      the function in which the <command>select</command> construct is
	      embedded.</para>
	      
	    <para>Compare this to the behavior of a 
	      <cmdsynopsis>
		<command>for</command>
		<arg choice="plain"><replaceable>variable</replaceable></arg>
		<arg choice="opt">in <replaceable>list</replaceable></arg>
	      </cmdsynopsis>
	      construct with the 
	      <userinput>in <replaceable>list</replaceable></userinput>
	      omitted.</para>

	    <example id="ex32">
	      <title>Creating menus using <command>select</command> in a function</title>
	      <programlisting>&ex32;</programlisting>
	    </example>	    

	    <para>See also <xref linkend="resistor">.</para>

	    </listitem>
	  </varlistentry>

      </variablelist>

    </sect1> <!-- Testing and Branching -->


  </chapter> <!-- Loops -->



  <chapter id="internal">
    <title>Internal Commands and Builtins</title>


      <indexterm>
	<primary>builtin</primary>
      </indexterm>


      <para><anchor id="builtinref">A <firstterm>builtin</firstterm>
	is a <command>command</command> contained within the Bash tool
	set, literally <emphasis>built in</emphasis>. This is either
	for performance reasons -- builtins execute faster than external
	commands, which usually require forking off a separate process
	-- or because a particular builtin needs direct access to the
	shell internals.</para>
      
      <para><anchor id="forkref"></para>

		 <sidebar>

		 <para>When a command or
		   the shell itself initiates (or
		   <emphasis>spawns</emphasis>) a new
		   subprocess to carry out a task, this is called
		   <emphasis>forking</emphasis>. This new process
		   is the <quote>child</quote>, and the process
		   that <emphasis>forked</emphasis> it off is the
		   <quote>parent</quote>. While the <emphasis>child
		   process</emphasis> is doing its work, the
		   <emphasis>parent process</emphasis> is still
		   executing.</para>

		 <para>Generally, a Bash <emphasis>builtin</emphasis>
		   does not fork a subprocess when it executes within
		   a script. An external system command or filter in
		   a script usually <emphasis>will</emphasis> fork a
		   subprocess.</para>

		   </sidebar>


      <para>A builtin may be a synonym to a system command of the same
	name, but Bash reimplements it internally.  For example,
	the Bash <command>echo</command> command is not the same as
	<filename>/bin/echo</filename>, although their behavior is
	almost identical.
	   <programlisting>#!/bin/bash

echo "This line uses the \"echo\" builtin."
/bin/echo "This line uses the /bin/echo system command."</programlisting>
	</para>

      <para><anchor id="keywordref">A <firstterm>keyword</firstterm>
	is a <emphasis>reserved</emphasis> word, token or
	operator. Keywords have a special meaning to the shell,
	and indeed are the building blocks of the shell's
	syntax. As examples, <quote><token>for</token></quote>,
	<quote><token>while</token></quote>, <quote>do</quote>, and
	<quote><token>!</token></quote> are keywords. Similar to a
	<emphasis>builtin</emphasis>, a keyword is hard-coded into Bash,
	but unlike a builtin, a keyword is not by itself a command,
	but part of a larger command structure.

	   <footnote><para>An exception to this is the <link
	     linkend="timref">time</link> command, listed in the official
	     Bash documentation as a keyword.</para></footnote>

	</para>


      <variablelist id="intio">
        <title><anchor id="intio1">I/O</title>

	<varlistentry>
	  <term><anchor id="echoref"><command>echo</command></term>
	  <indexterm>
	    <primary>echo</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>echo</secondary>
	  </indexterm>
	  <listitem>
	    <para>prints (to <filename>stdout</filename>) an expression
	      or variable (see <xref linkend="ex9">). 
	      <programlisting>echo Hello
echo $a</programlisting></para>
	    
	    <para>An <command>echo</command> requires the
	      <option>-e</option> option to print escaped characters. See
	      <xref linkend="escaped">.</para>

	    <para>Normally, each <command>echo</command> command prints
	      a terminal newline, but the <option>-n</option> option
	      suppresses this.</para>

	    <note>
	    <para>An <command>echo</command> can be used to feed a
	      sequence of commands down a pipe.</para>
	    <para><programlisting>if echo "$VAR" | grep -q txt   # if [[ $VAR = *txt* ]]
then
  echo "$VAR contains the substring sequence \"txt\""
fi</programlisting></para>  
	    </note>  

	    <note><para>An <command>echo</command>, in combination with
	      <link linkend="commandsubref">command substitution</link>
	      can set a variable.</para> <para><userinput>a=`echo
	      "HELLO" | tr A-Z a-z`</userinput></para>
	      <para>See also <xref linkend="lowercase">, <xref
	      linkend="ex57">, <xref linkend="monthlypmt">, and <xref
	      linkend="base">.</para></note>


	    <para>Be aware that <command>echo `command`</command>
	      deletes any linefeeds that the output
	      of <replaceable>command</replaceable>
	      generates.</para>
	      
	    <para>The <link linkend="ifsref">$IFS</link> (internal field
	      separator) variable normally contains
	      <token>\n</token> (linefeed) as one of its set of
	      <link linkend="whitespaceref">whitespace</link>
	      characters. Bash therefore splits the output of
	      <replaceable>command</replaceable> at linefeeds
	      into arguments to <command>echo</command>.  Then
	      <command>echo</command> outputs these arguments,
	      separated by spaces.</para>
	      
	    <para>
	      <screen>
<prompt>bash$ </prompt><userinput>ls -l /usr/share/apps/kjezz/sounds</userinput>
<computeroutput>-rw-r--r--    1 root     root         1407 Nov  7  2000 reflect.au
 -rw-r--r--    1 root     root          362 Nov  7  2000 seconds.au</computeroutput>




<prompt>bash$ </prompt><userinput>echo `ls -l /usr/share/apps/kjezz/sounds`</userinput>
<computeroutput>total 40 -rw-r--r-- 1 root root 716 Nov 7 2000 reflect.au -rw-r--r-- 1 root root 362 Nov 7 2000 seconds.au</computeroutput>
	      </screen>
	    </para>

	    <note>
	    <para>This command is a shell builtin, and not the same as
	      <filename>/bin/echo</filename>, although its behavior is
	      similar.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>type -a echo</userinput>
<computeroutput>echo is a shell builtin
 echo is /bin/echo</computeroutput>
	      </screen>
	  </para>
	    </note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="printfref"><command>printf</command></term>
	  <indexterm>
	    <primary>printf</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>printf</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>printf</command>, formatted print, command is an
	      enhanced <command>echo</command>.  It is a limited variant
	      of the C language <function>printf()</function> library
	      function, and its syntax is somewhat different.</para>
	    <cmdsynopsis>
	      <command>printf</command>
	      <arg choice=plain rep=repeat><replaceable>format-string</replaceable></arg>
	      <arg choice=plain rep=repeat><replaceable>parameter</replaceable></arg>
	    </cmdsynopsis>

	    <para>This is the Bash builtin version
	      of the <filename>/bin/printf</filename> or
	      <filename>/usr/bin/printf</filename> command. See the
	      <command>printf</command> manpage (of the system command)
	      for in-depth coverage.</para>

	    <caution><para>Older versions of Bash may not support
	      <command>printf</command>.</para></caution>

	    <example id="ex47">
	      <title><command>printf</command> in action</title>
	      <programlisting>&ex47;</programlisting>
	    </example>

	    <para>Formatting error messages is a useful application of
	      <command>printf</command></para>

            <para>
	        <programlisting>E_BADDIR=65

var=nonexistent_directory

error()
{
  printf "$@" >&2
  # Formats positional params passed, and sents them to stderr.
  echo
  exit $E_BADDIR
}

cd $var || error $"Can't cd to %s." "$var"

# Thanks, S.C.</programlisting>
            </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="readref"><command>read</command></term> <indexterm>
	    <primary>read</primary>
	  </indexterm> <indexterm>
	    <primary>command</primary> <secondary>read</secondary>
	  </indexterm> <listitem><para><quote>Reads</quote> the value
	    of a variable from <filename>stdin</filename>, that
	    is, interactively fetches input from the keyboard. The
	    <option>-a</option> option lets <command>read</command>
	    get array variables (see <xref linkend="ex67">).</para>

	    <example id="ex36">
	      <title>Variable assignment, using <command>read</command></title>
	      <programlisting>&ex36;</programlisting>
	    </example>


	    <para>A <command>read</command> without an associated variable
	      assigns its input to the dedicated variable <link
	      linkend="replyref">$REPLY</link>.</para>

	    <example id="readnovar">
	      <title>What happens when <command>read</command> has no
	        variable</title>
	      <programlisting>&readnovar;</programlisting>
	    </example>


	    <para>Normally, inputting a <userinput>\</userinput>
	      suppresses a newline during input to
	      a <command>read</command>. The <option>-r</option>
	      option causes an inputted <userinput>\</userinput> to be
	      interpreted literally.</para>

	    <example id="readr">
	      <title>Multi-line input to <command>read</command></title>
	      <programlisting>&readr;</programlisting>
	    </example>

	    
	    <para>The <command>read</command> command has some interesting
	      options that permit echoing a prompt and even reading keystrokes
	      without hitting <keycap>ENTER</keycap>.</para>

	    <para><programlisting># Read a keypress without hitting ENTER.

read -s -n1 -p "Hit a key " keypress
echo; echo "Keypress was "\"$keypress\""."

# -s option means do not echo input.
# -n N option means accept only N characters of input.
# -p option means echo the following prompt before reading input.

# Using these options is tricky, since they need to be in the correct order.</programlisting></para>


	    <para>The <option>-n</option> option to <command>read</command>
	      also allows detection of the <emphasis>arrow keys</emphasis>
	      and certain of the other unusual keys.</para>

	    <example id="arrowdetect">
	      <title>Detecting the arrow keys</title>
	      <programlisting>&arrowdetect;</programlisting>
	    </example>


	    <para>The <option>-t</option> option to <command>read</command>
	      permits timed input (see <xref linkend="tout">).</para>

	    <para>The <command>read</command> command may also
	      <quote>read</quote> its variable value from a file
	      <link linkend="ioredirref">redirected</link> to
	      <filename>stdin</filename>.  If the file contains
	      more than one line, only the first line is assigned
	      to the variable. If <command>read</command>
	      has more than one parameter, then each of
	      these variables gets assigned a successive <link
	      linkend="whitespaceref">whitespace-delineated</link>
	      string. Caution!</para>

	    <example id="readredir">
	      <title>Using <command>read</command> with
	        <link linkend="ioredirref">file redirection</link></title>
	      <programlisting>&readredir;</programlisting>
	    </example>

	    <note>

	    <para><link linkend="piperef">Piping</link> output
	      to a <command>read</command>, using <link
	      linkend="echoref">echo</link> to set variables <link
	      linkend="badread0">will fail</link>.</para>

	    <para>However, piping the output of <link
	      linkend="catref">cat</link> does seem to work.
	        <programlisting>cat file1 file2 |
while read line
do
echo $line
done</programlisting></para>
	      </note>
	      

	    </listitem>
	  </varlistentry>

      </variablelist>

      <variablelist id="intfilesystem">
        <title><anchor id="intfilesystem1">Filesystem</title>

	<varlistentry>
	  <term><command>cd</command></term>
	  <indexterm>
	    <primary>cd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cd</secondary>
	  </indexterm>
	  <listitem>
	    <para>The familiar <command>cd</command> change directory
	      command finds use in scripts where execution of a command
	      requires being in a specified directory.</para>

	    <para>  
	      <programlisting>(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)</programlisting>
	      [from the <link linkend="coxex">previously cited</link>
	      example by Alan Cox]</para>

	    <para>The <option>-P</option> (physical) option to
	      <command>cd</command> causes it to ignore symbolic
	      links.</para>

	    <para><command>cd -</command> changes to <link
	    linkend="oldpwd">$OLDPWD</link>, the previous working
	    directory.</para>

	    <para><anchor id="doubleslashref"></para>

	    <caution><para>The <command>cd</command> command does not function
	      as expected when presented with two forward slashes.

	      <screen>
<prompt>bash$ </prompt><userinput>cd //</userinput>
<prompt>bash$ </prompt><userinput>pwd</userinput>
<computeroutput>//</computeroutput>
	      </screen>
	      The output should, of course, be <computeroutput>/</computeroutput>.
	      This is a problem both from the command line and in a script.</para></caution>

	  </listitem>
	</varlistentry>

      <varlistentry>
	<term><anchor id="pwd2ref"><command>pwd</command></term>
	  <indexterm>
	    <primary>pwd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>pwd</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>$PWD</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PWD</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>directory</primary>
	    <secondary>working</secondary>
	  </indexterm>
	  <listitem><para>Print Working Directory. This gives the user's
	      (or script's) current directory (see <xref
	      linkend="ex37">). The effect is identical to
	      reading the value of the builtin variable <link
	      linkend="pwdref">$PWD</link>.</para>

	  </listitem>
	</varlistentry>

      <varlistentry>
	<term><anchor id="dirsd"><command>pushd</command></term>
	<term><command>popd</command></term>
	<term><command>dirs</command></term>
	  <indexterm>
	    <primary>pushd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>pushd</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>popd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>popd</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>dirs</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>dirs</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>directory</primary>
	    <secondary>working</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>bookmark</primary>
	  </indexterm>
	  <listitem><para>This command set is a mechanism for bookmarking working directories,
	      a means of moving back and forth through directories in an orderly
	      manner.  A pushdown stack is used to keep track of directory names.
	      Options allow various manipulations of the directory stack.</para>

	    <para><anchor id="pushdref"><userinput>pushd
	      dir-name</userinput> pushes the path
	      <replaceable>dir-name</replaceable> onto the directory
	      stack and simultaneously changes the current working
	      directory to <replaceable>dir-name</replaceable></para>

	    <para><anchor id="popdref"><command>popd</command> removes
	      (pops) the top directory path name off the directory stack
	      and simultaneously changes the current working directory
	      to that directory popped from the stack.</para>
	    
	    <para><command>dirs</command> lists the contents of the directory
	      stack (compare this with the <link
	      linkend="dirstackref">$DIRSTACK</link> variable).
	      A successful <command>pushd</command> or
	      <command>popd</command> will automatically invoke
	      <command>dirs</command>.</para>


	    <para>Scripts that require various changes to the current
	      working directory without hard-coding the directory name
	      changes can make good use of these commands. Note that
	      the implicit <varname>$DIRSTACK</varname> array variable,
	      accessible from within a script, holds the contents of
	      the directory stack.
	    </para>

	    <example id="ex37">
	      <title>Changing the current working directory   </title>
	      <programlisting>&ex37;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="intvar">
        <title><anchor id="intvar1">Variables</title>

	<varlistentry>
	  <term><anchor id="letref"><command>let</command></term>
	  <indexterm>
	    <primary>let</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>let</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>let</command> command carries out arithmetic
	      operations on variables. In many cases, it functions as a less
	      complex version of <link linkend="exprref">expr</link>.</para>

	    <example id="ex46">
	      <title>Letting <command>let</command> do some arithmetic.</title>
	      <programlisting>&ex46;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="evalref"><command>eval</command></term>
	  <indexterm>
	    <primary>eval</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>eval</secondary>
	  </indexterm>
	  <listitem>
	    
	    <para><userinput>eval arg1 [arg2] ... [argN]</userinput></para>
	    
	    <para>Translates into commands the arguments in a list
	      (useful for code generation within a script).</para>

	    <example id="ex43">
	      <title>Showing the effect of <command>eval</command></title>
	      <programlisting>&ex43;</programlisting>
	    </example>	    

	    <example id="ex44">
	      <title>Forcing a log-off</title>
	      <programlisting>&ex44;</programlisting>
	    </example>	    

	    <example id="rot14">
	      <title>A version of <quote>rot13</quote></title>
	      <programlisting>&rot14;</programlisting>
	    </example>	    

	    <para>Rory Winston contributed the following instance of how
	      useful <command>eval</command> can be.</para>

	    <example id="evalex">
	      <title>Using <command>eval</command> to force variable
	        substitution in a Perl script</title>
	      <programlisting>&evalex;</programlisting>
	    </example>	    



	    <caution><para>The <command>eval</command> command can be
	      risky, and normally should be avoided when there
	      exists a reasonable alternative. An <userinput>eval
	      $COMMANDS</userinput> executes the contents of
	      <replaceable>COMMANDS</replaceable>, which may
	      contain such unpleasant surprises as <command>rm -rf
	      *</command>. Running an <command>eval</command> on
	      unfamiliar code written by persons unknown is living
	      dangerously.</para></caution>


	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="setref"><command>set</command></term>
	  <indexterm>
	    <primary>set</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>set</secondary>
	  </indexterm>
	  <listitem><para>The <command>set</command> command changes
	      the value of internal script variables. One use for
	      this is to toggle <link linkend="optionsref">option
	      flags</link> which help determine the behavior of the
	      script. Another application for it is to reset the <link
	      linkend="posparamref">positional parameters</link> that
	      a script sees as the result of a command (<userinput>set
	      `command`</userinput>). The script can then parse the
	      fields of the command output.</para>

	    <example id="ex34">
	      <title>Using <command>set</command> with positional
	        parameters</title>
	      <programlisting>&ex34;</programlisting>
	    </example>

	    <para>Invoking <command>set</command> without any options or
	      arguments simply lists all the <link
	      linkend="envref">environmental</link> and other variables
	      that have been initialized.
	      <screen>
<prompt>bash$ </prompt><userinput>set</userinput>
<computeroutput>AUTHORCOPY=/home/bozo/posts
 BASH=/bin/bash
 BASH_VERSION=$'2.05.8(1)-release'
 ...
 XAUTHORITY=/home/bozo/.Xauthority
 _=/etc/bashrc
 variable22=abc
 variable23=xzy</computeroutput>
	      </screen>
            </para>


	    <para>Using <command>set</command> with the <option>--</option>
	      option explicitly assigns the contents of a variable to
	      the positional parameters. When no variable follows the
	      <option>--</option>, it <emphasis>unsets</emphasis>
	      the positional parameters.</para>

	    <example id="setpos">
	      <title>Reassigning the positional parameters</title>
	      <programlisting>&setpos;</programlisting>
	    </example>

	    <para>See also <xref linkend="ex22a"> and <xref linkend="ex33a">.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="unsetref"><command>unset</command></term>
	  <indexterm>
	    <primary>unset</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>unset</secondary>
	  </indexterm>
	  <listitem><para>The <command>unset</command> command deletes a
	      shell variable, effectively setting it to
	      <emphasis>null</emphasis>. Note that this command does
	      not affect positional parameters.</para>

	  <para>
	      <screen>
<prompt>bash$ </prompt><userinput>unset PATH</userinput>

<prompt>bash$ </prompt><userinput>echo $PATH</userinput>
<computeroutput>


</computeroutput>
<prompt>bash$ </prompt></screen>
	    </para>

	    <example id="uns">
	      <title><quote>Unsetting</quote> a variable</title>
	      <programlisting>&uns;</programlisting>
	    </example>

	    </listitem>
	  </varlistentry>

	<varlistentry>
	  <term><anchor id="exportref"><command>export</command></term>
	  <indexterm>
	    <primary>export</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>export</secondary>
	  </indexterm>
	  <listitem><para>The <command>export</command> command makes
	      available variables to all child processes of the
	      running script or shell. Unfortunately, there is no way
	      to <command>export</command> variables back to the parent
	      process, to the process that called or invoked the script
	      or shell. One important use of <command>export</command>
	      command is in <link linkend="filesref1">startup
	      files</link>, to initialize and make accessible <link
	      linkend="envref">environmental variables</link> to
	      subsequent user processes.</para>


	  <example id="coltotaler3">
	    <title>Using <command>export</command> to pass a variable to an
	      embedded <link linkend="awkref">awk</link> script</title>
	    <programlisting>&coltotaler3;</programlisting>
	  </example>



	      <tip>

	        <para>It is possible to initialize and export
		  variables in the same operation, as in <command>export
		  var1=xxx</command>.</para>

		<para>However, as Greg Keraunen points out, in certain
		  situations this may have a different effect than
		  setting a variable, then exporting it.</para>

	        <para>
	        <screen>
<prompt>bash$ </prompt><userinput>export var=(a b); echo ${var[0]}</userinput>
<computeroutput>(a b)</computeroutput>



<prompt>bash$ </prompt><userinput>var=(a b); export var; echo ${var[0]}</userinput>
<computeroutput>a</computeroutput>
	      </screen>
	    </para>

	       	
              </tip>

	    </listitem>
	  </varlistentry>
	
	<varlistentry>
	  <term><command>declare</command></term>
	  <term><command>typeset</command></term>
	  <indexterm>
	    <primary>declare</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>declare</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>typeset</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>typeset</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <link linkend="declareref">declare</link> and
	      <link linkend="declareref">typeset</link> commands specify
	      and/or restrict properties of variables.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>readonly</command></term>
	  <indexterm>
	    <primary>readonly</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>readonly</secondary>
	  </indexterm>
	  <listitem><para>Same as <link linkend="declareref">declare -r</link>,
	      sets a variable as read-only, or, in effect, as a
	      constant. Attempts to change the variable fail with an
	      error message. This is the shell analog of the C language
	      <command>const</command> type qualifier.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="getoptsx"><command>getopts</command></term>
	  <indexterm>
	    <primary>getopts</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>getopts</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>$OPTIND</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$OPTIND</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>$OPTARG</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$OPTARG</secondary>
	  </indexterm>
	  <listitem>
	    <para>This powerful tool parses command-line arguments passed
	      to the script. This is the Bash analog of the <link
	      linkend="getopty">getopt</link> external command and
	      the <command>getopt</command> library function familiar
	      to C programmers. It permits passing and concatenating
	      multiple options

	      <footnote><para>A option is an argument that acts as a
		flag, switching script behaviors on or off. The
		argument associated with a particular option indicates
		the behavior that the option (flag) switches on or
		off.</para></footnote>

	      and associated arguments to a script (for
	      example <userinput>scriptname -abc -e
	      /usr/local</userinput>).</para>

	    <para>The <command>getopts</command> construct uses two implicit
	      variables. <varname>$OPTIND</varname> is the argument
	      pointer (<wordasword>OPTion INDex</wordasword>)
	      and <varname>$OPTARG</varname> (<wordasword>OPTion
	      ARGument</wordasword>) the (optional) argument attached
	      to an option. A colon following the option name in the
	      declaration tags that option as having an associated
	      argument.</para>

	    <para>A <command>getopts</command> construct usually comes
	      packaged in a <link linkend="whileloopref">while
	      loop</link>, which processes the options and
	      arguments one at a time, then decrements the implicit
	      <varname>$OPTIND</varname> variable to step to the
	      next.</para>

	    <note>
	      <para>
		<orderedlist>
		  <listitem>

		    <para>The arguments passed from the command line to
		      the script must be preceded by a
		      minus (<option>-</option>) or a plus
		      (<option>+</option>).  It is the prefixed
		      <option>-</option> or <option>+</option> that lets
		      <command>getopts</command> recognize command-line
		      arguments as <emphasis>options</emphasis>.
		      In fact, <command>getopts</command> will not process
		      arguments without the prefixed <option>-</option>
		      or <option>+</option>, and will terminate option
		      processing at the first argument encountered
		      lacking them.</para>

		  </listitem>
		  <listitem><para>The <command>getopts</command> template
		      differs slightly from the standard <command>while</command>
		      loop, in that it lacks condition brackets.</para>
		  </listitem>
		  <listitem>

		  <para>The <command>getopts</command> construct replaces
		     the obsolete and less powerful <link
		     linkend="getopty">getopt</link> external
		     command.</para>

		   </listitem>
		</orderedlist>
	      </para>
	    </note>

	    <para><programlisting>
while getopts ":abcde:fg" Option
# Initial declaration.
# a, b, c, d, e, f, and g are the options (flags) expected.
# The : after option 'e' shows it will have an argument passed with it.
do
  case $Option in
    a ) # Do something with variable 'a'.
    b ) # Do something with variable 'b'.
    ...
    e)  # Do something with 'e', and also with $OPTARG,
        # which is the associated argument passed with option 'e'.
    ...
    g ) # Do something with variable 'g'.
  esac
done
shift $(($OPTIND - 1))
# Move argument pointer to next.

# All this is not nearly as complicated as it looks &lt;grin&gt;.
	      </programlisting></para>

	    <example id="ex33">
	      <title>Using <command>getopts</command> to read the
	        options/arguments passed to a script</title>
	      <programlisting>&ex33;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="intscrbeh">
        <title><anchor id="intscrbeh1">Script Behavior</title>

      <varlistentry>
	<term><anchor id="sourceref"><command>source</command></term>
	<term><token>.</token> (<link linkend="dotref">dot</link> command)</term>
	  <indexterm>
	    <primary>source</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>source</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>.</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>.</secondary>
	  </indexterm>

	  <listitem>
	  
	  <para>This command, when invoked from the command line,
	      executes a script. Within a script, a
	      <userinput>source file-name</userinput> loads the file
	      <filename>file-name</filename>. This is the shell scripting
	      equivalent of a C/C++ <userinput>#include</userinput>
	      directive. It is useful in situations when multiple scripts
	      use a common data file or function library.</para>

	    <example id="ex38">
	      <title><quote>Including</quote> a data file</title>
	      <programlisting>&ex38;</programlisting>

	      <para>File <filename>data-file</filename> for <xref
		linkend="ex38">, above.  Must be present in same
		directory.</para>

	      <programlisting>&ex38bis;</programlisting>
	    </example>	    

	  <para>It is even possible for a script to
	    <emphasis>source</emphasis> itself, though this does not
	    seem to have any practical applications.</para>

	    <example id="selfsource">
	      <title>A (useless) script that sources itself</title>
	      <programlisting>&selfsource;</programlisting>
	    </example>

	    </listitem>
	  </varlistentry>


	<varlistentry>
	  <term><command>exit</command></term>
	  <indexterm>
	    <primary>exit</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>exit</secondary>
	  </indexterm>
	  <listitem>
	    <para>Unconditionally terminates a script. The
		<command>exit</command> command may optionally take an
		integer argument, which is returned to the shell as
		the <link linkend="exitstatusref">exit status</link>
		of the script. It is good practice to end all but the
		simplest scripts with an <userinput>exit 0</userinput>,
		indicating a successful run.</para>

	    <note><para>If a script terminates with an <command>exit</command>
	      lacking an argument, the exit status of the script is the exit
	      status of the last command executed in the script, not counting
	      the <command>exit</command>.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="execref"><command>exec</command></term>
	  <indexterm>
	    <primary>exec</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>exec</secondary>
	  </indexterm>
	  <listitem>

	    <para>This	shell builtin replaces the current process with
	      a specified command. Normally, when the shell encounters
	      a command, it <link linkend="forkref">forks off</link> a
	      child process to actually execute the command.  Using the
	      <command>exec</command> builtin, the shell does not fork,
	      and the command exec'ed replaces the shell.  When used in
	      a script, therefore, it forces an exit from the script when
	      the <command>exec</command>'ed command terminates. For this
	      reason, if an <command>exec</command> appears in a script,
	      it would probably be the final command.</para>

	    <example id="ex54">
	      <title>Effects of <command>exec</command></title>
	      <programlisting>&ex54;</programlisting>
	    </example>	    	   

	    <example id="selfexec">
	      <title>A script that <command>exec's</command> itself</title>
	      <programlisting>&selfexec;</programlisting>
	    </example>	    	   

	    <para>An <command>exec</command> also serves to reassign <link
	      linkend="fdref">file descriptors</link>.	<userinput>exec
	      &lt;zzz-file</userinput> replaces <filename>stdin</filename>
	      with the file <filename>zzz-file</filename> (see <xref
	      linkend="redir1">).</para>

	    <note><para>The <option>-exec</option> option to
	      <link linkend="findref">find</link> is
	      <replaceable>not</replaceable> the same as the
	      <command>exec</command> shell builtin.</para></note>

	  </listitem>
	</varlistentry>
	

	<varlistentry>
	  <term><command>shopt</command></term>
	  <indexterm>
	    <primary>shopt</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>shopt</secondary>
	  </indexterm>
	  <listitem>
	    <para>This command permits changing shell options on the fly (see
	      <xref linkend="al"> and <xref linkend="unal">).  It often
	      appears in the Bash <link linkend="filesref1">startup
	      files</link>, but also has its uses in scripts. Needs
	      <link linkend="bash2ref">version 2</link> or later of Bash.

	      <programlisting>shopt -s cdspell
# Allows minor misspelling of directory names with 'cd'

cd /hpme  # Oops! Mistyped '/home'.
pwd       # /home
          # The shell corrected the misspelling.</programlisting></para>

	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="intcommand">
        <title><anchor id="intcommand1">Commands</title>

      <varlistentry>
	<term><anchor id="trueref"><command>true</command></term>
	  <indexterm>
	    <primary>true</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>true</secondary>
	  </indexterm>
	  <listitem><para>A command that returns a successful
	    (<returnvalue>zero</returnvalue>) <link
	    linkend="exitstatusref">exit status</link>, but does
	    nothing else.
	  </para>

	  <para><programlisting># Endless loop
while true   # alias for ":"
do
   operation-1
   operation-2
   ...
   operation-n
   # Need a way to break out of loop or script will hang.
done</programlisting></para>

	    </listitem>
	  </varlistentry>

      <varlistentry>
	<term><command>false</command></term>
	  <indexterm>
	    <primary>false</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>false</secondary>
	  </indexterm>
	  <listitem><para>A command that returns an unsuccessful <link
	  linkend="exitstatusref">exit status</link>,
	    but does nothing else.</para>

	  <para><programlisting># Null loop
while false
do
   # The following code will not execute.
   operation-1
   operation-2
   ...
   operation-n
   # Nothing happens!
done   
</programlisting></para>

	    </listitem>
	  </varlistentry>

      <varlistentry>
	<term><command>type [cmd]</command></term>
	  <indexterm>
	    <primary>type</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>type</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>which</secondary>
	  </indexterm>
	  <listitem><para>Similar to the <link
	    linkend="whichref">which</link> external command,
	    <command>type cmd</command> gives the full pathname to
	    <quote>cmd</quote>. Unlike <command>which</command>,
	    <command>type</command> is a Bash builtin. The useful
	    <option>-a</option> option to <command>type</command>
	    identifies <replaceable>keywords</replaceable>
	    and <replaceable>builtins</replaceable>, and also locates
	    system commands with identical names.</para>

	    <para>
	      <screen>
<prompt>bash$ </prompt><userinput>type '['</userinput>
<computeroutput>[ is a shell builtin</computeroutput>
<prompt>bash$ </prompt><userinput>type -a '['</userinput>
<computeroutput>[ is a shell builtin
 [ is /usr/bin/[</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

      <varlistentry>
	<term><command>hash [cmds]</command></term>
	  <indexterm>
	    <primary>hash</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>hash</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>$PATH</primary>
	  </indexterm>
	  <indexterm>
	    <primary>variable</primary>
	    <secondary>$PATH</secondary>
	  </indexterm>
	  <listitem><para>Record the path name of specified commands (in the
	      shell hash table), so the shell or script will not need to search
	      the <varname>$PATH</varname> on subsequent calls to those
              commands. When <command>hash</command> is called with no
	      arguments,  it simply lists the commands that have been hashed.
	      The <option>-r</option> option resets the hash table.</para>
	  </listitem>
	</varlistentry>

      <varlistentry>
	<term><command>help</command></term>
	  <indexterm>
	    <primary>help</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary></secondary>
	  </indexterm>
	  <listitem>
	  
	  <para><command>help</command> COMMAND looks up
	    a short usage summary of the shell builtin COMMAND.  This is
	    the counterpart to <link linkend="whatisref">whatis</link>,
	    but for builtins.</para>

	      <para>
	      <screen><prompt>bash$ </prompt><userinput>help exit</userinput>
<computeroutput>exit: exit [n]
    Exit the shell with a status of N.  If N is omitted, the exit status
    is that of the last command executed.</computeroutput>
	      </screen>
	      </para>
	  </listitem>
	</varlistentry>

      </variablelist>


      <sect1>
	<title>Job Control Commands</title>


	<para>Certain of the following job control commands take a
	  <quote>job identifier</quote> as an argument. See the <link
	  linkend="jobidtable">table</link> at end of the chapter.</para>

	<variablelist id="jccommandlist">

	  <varlistentry>
	    <term><command>jobs</command></term>
	  <indexterm>
	    <primary>jobs</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>jobs</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>ps</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>ps</secondary>
	  </indexterm>
	    <listitem>

	      <para>Lists the jobs running in the background, giving the job number.
		Not as useful as <command>ps</command>.</para>

              <note>
	      <para>It is all too easy to confuse
		<emphasis>jobs</emphasis> and
		<emphasis>processes</emphasis>.  Certain <link
		linkend="builtinref">builtins</link>, such as
		<command>kill</command>, <command>disown</command>, and
		<command>wait</command> accept either a job number or a
		process number as an argument. The <command>fg</command>,
		<command>bg</command> and <command>jobs</command>
		commands accept only a job number.</para>

	      <para>
	      <screen><prompt>bash$ </prompt><userinput>sleep 100 &</userinput>
<computeroutput>[1] 1384</computeroutput>

<prompt>bash $ </prompt><userinput>jobs</userinput>
<computeroutput>[1]+  Running                 sleep 100 &</computeroutput></screen>
	      </para>

	      <para><quote>1</quote> is the job number (jobs are
		maintained by the current shell), and <quote>1384</quote>
		is the process number (processes are maintained by
		the system). To kill this job/process, either a <command>kill
		%1</command> or a <command>kill 1384</command> works.</para>

	      <para><emphasis>Thanks, S.C.</emphasis></para>	
               </note>

	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><command>disown</command></term>
	  <indexterm>
	    <primary>disown</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>disown</secondary>
	  </indexterm>
	    <listitem>
	      <para>Remove job(s) from the shell's table of active jobs.</para>
	    </listitem>
	  </varlistentry>


	<varlistentry>
	  <term><command>fg</command></term>
	  <term><command>bg</command></term>
	  <indexterm>
	    <primary>fg</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>foreground</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>background</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>bg</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>fg</command> command switches a job
	      running in the background into the foreground.  The
	      <command>bg</command> command restarts a suspended job, and
	      runs it in the background. If no job number is specified,
	      then the <command>fg</command> or <command>bg</command>
	      command acts upon the currently running job.</para>
	  </listitem>
	</varlistentry>

	  <varlistentry>
	    <term><anchor id="waitref"><command>wait</command></term>
	  <indexterm>
	    <primary>wait</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>wait</secondary>
	  </indexterm>
	    <listitem>

	      <para>Stop script execution until all jobs running in
	        background have terminated, or until the job number or
	        process id specified as an option terminates. Returns the <link
	        linkend="exitstatusref">exit status</link> of waited-for
	        command.</para>

	      <para>You may use the <command>wait</command> command
		to prevent a script from exiting before a background
		job finishes executing (this would create a dreaded
		orphan process).</para>

	    <example id="ex39">
	      <title>Waiting for a process to finish before proceeding</title>
	      <programlisting>&ex39;</programlisting>
	    </example>	    

	      <para>Optionally, <command>wait</command> can take a job
		identifier as an argument, for example,
		<command>wait%1</command> or <command>wait
		$PPID</command>. See the <link linkend="jobidtable">job
		id table</link>.</para>

	      <para><anchor id="waithang"></para>
              <tip>
	      <para>Within a script, running a command in the background
		with an ampersand (&amp;) may cause the script
		to hang until <keycap>ENTER</keycap> is hit. This
		seems to occur with commands that write to
		<filename>stdout</filename>. It can be a major annoyance.
		  <programlisting>#!/bin/bash
# test.sh		  

ls -l &
echo "Done."</programlisting>
	      <screen><prompt>bash$ </prompt><userinput>./test.sh</userinput>
<computeroutput>Done.
 [bozo@localhost test-scripts]$ total 1
 -rwxr-xr-x    1 bozo     bozo           34 Oct 11 15:09 test.sh
 _
</computeroutput>
               </screen>
	       </para>

              <para>Placing a <command>wait</command> after the background
                command seems to remedy this.
		  <programlisting>#!/bin/bash
# test.sh		  

ls -l &
echo "Done."
wait</programlisting>
	      <screen><prompt>bash$ </prompt><userinput>./test.sh</userinput>
<computeroutput>Done.
 [bozo@localhost test-scripts]$ total 1
 -rwxr-xr-x    1 bozo     bozo           34 Oct 11 15:09 test.sh</computeroutput>
               </screen>
	        <link linkend="ioredirref">Redirecting</link> the
                output of the command to a file or even to
		<filename>/dev/null</filename> also takes care of this
		problem.
              </para>
	      </tip>


	    </listitem>
	  </varlistentry>


	  <varlistentry>
	    <term><command>suspend</command></term>
	    <indexterm>
	      <primary>suspend</primary>
	    </indexterm>
	    <indexterm>
	      <primary>command</primary>
	      <secondary>suspend</secondary>
	    </indexterm>
	    <listitem>
	      <para>This has a similar effect to
		<keycombo><keycap>Control</keycap><keycap>Z</keycap></keycombo>, 
		but it suspends the shell (the shell's parent process should
		resume it at an appropriate time).</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><command>logout</command></term>
	  <indexterm>
	    <primary>logout</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>log out</secondary>
	  </indexterm>
	    <listitem>
	      <para>Exit a login shell, optionally specifying an <link
	        linkend="exitstatusref">exit status</link>.</para>
	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><anchor id="timesref"><command>times</command></term>
	  <indexterm>
	    <primary>times</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>times</secondary>
	  </indexterm>
	    <listitem>
	      <para>Gives statistics on the system time used in executing commands, in the
		following form:
		<screen><computeroutput>0m0.020s 0m0.020s</computeroutput></screen>
		This capability is of very limited value, since it is uncommon to
		profile and benchmark shell scripts.</para>

	    </listitem>
	  </varlistentry>

	  <varlistentry>
	    <term><anchor id="killref"><command>kill</command></term>
	  <indexterm>
	    <primary>kill</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>kill</secondary>
	    </indexterm>
	    <listitem>
	      <para>Forcibly terminate a process by sending it an
	      appropriate <emphasis>terminate</emphasis> signal (see <xref
	      linkend="killprocess">).</para>

	    <example id="selfdestruct">
	      <title>A script that kills itself</title>
	      <programlisting>&selfdestruct;</programlisting>
	    </example>
	      
	      <note><para><userinput>kill -l</userinput> lists all the
		<link linkend="signald">signals</link>.  A <userinput>kill
		-9</userinput> is a <quote>sure kill</quote>, which will
		usually terminate a process that stubbornly refuses to
		die with a plain <command>kill</command>. Sometimes, a
		<userinput>kill -15</userinput> works. A <quote>zombie
		process</quote>, that is, a process whose <link
		linkend="forkref">parent</link> has terminated, cannot be
		killed (you can't kill something that is already dead),
		but <command>init</command> will generally clean it up
		sooner or later.</para></note>

	    </listitem>
	  </varlistentry>

	<varlistentry>
	  <term><command>command</command></term>
	  <indexterm>
	    <primary>command</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>command</secondary>
	  </indexterm>
	  <listitem><para>The <command>command COMMAND</command> directive
	    disables aliases and functions for the command
	    <quote>COMMAND</quote>.</para>

	    <note><para>This is one of three shell directives that
	      effect script command processing. The others are
	      <link linkend="bltref">builtin</link> and <link
	      linkend="enableref">enable</link>.</para></note>
	    </listitem>
	  </varlistentry>

	<varlistentry>
	  <term><anchor id="bltref"><command>builtin</command></term>
	  <indexterm>
	    <primary>builtin</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>builtin</secondary>
	  </indexterm>
	  <listitem><para>Invoking <command>builtin
	      BUILTIN_COMMAND</command> runs the command
	      <quote>BUILTIN_COMMAND</quote> as a shell <link
	      linkend="builtinref">builtin</link>, temporarily disabling
	      both functions and external system commands with the
	      same name.</para>
	    </listitem>
	  </varlistentry>

	<varlistentry>
	  <term><anchor id="enableref"><command>enable</command></term>
	  <indexterm>
	    <primary>enable</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>enable</secondary>
	  </indexterm>
	  <listitem>

	    <para>This either enables or disables a shell
	      builtin command. As an example, <command>enable -n
	      kill</command> disables the shell builtin <link
	      linkend="killref">kill</link>, so that when Bash
	      subsequently encounters <command>kill</command>, it invokes
	      <filename>/bin/kill</filename>.</para>
	      
	    <para><anchor id="enableref1">The <option>-a</option>
	      option to <command>enable</command> lists all the
	      shell builtins, indicating whether or not they
	      are enabled. The <option>-f filename</option>
	      option lets <command>enable</command> load a <link
	      linkend="builtinref">builtin</link> as a shared library
	      (DLL) module from a properly compiled object file.
	        <footnote>
		  <para>The C source for a number of loadable builtins is
		    typically found in the <filename
		    class="directory">/usr/share/doc/bash-?.??/functions</filename>
		    directory.</para>
		  <para>Note that the <option>-f</option> option to
		    <command>enable</command> is not portable to all
		    systems.</para>
		</footnote>.
	     </para>	

	    </listitem>
	  </varlistentry>

	<varlistentry>
	  <term><command>autoload</command></term>
	  <indexterm>
	    <primary>autoload</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>autoloader</secondary>
	  </indexterm>
	  <listitem>

	  <para>This is a port to Bash of the
	    <emphasis>ksh</emphasis> autoloader. With
	    <command>autoload</command> in place, a function with
	    an <quote>autoload</quote> declaration will load from an
	    external file at its first invocation.
	      <footnote><para>The same effect as
	      <command>autoload</command> can be achieved with <link
	      linkend="declareref">typeset -fu</link>.</para></footnote>
	    This saves system resources.</para>

	  <para>Note that <command>autoload</command> is not a part of the
	    core Bash installation. It needs to be loaded in with
	    <command>enable -f</command> (see above).</para>

	    </listitem>
	  </varlistentry>

	</variablelist>

      <table id="jobidtable">
	<title>Job identifiers</title>
	<tgroup cols="2">
	  <thead>
	    <row>
	      <entry>Notation</entry>
	      <entry>Meaning</entry>
	    </row>
	  </thead>
	  <tbody>
	    <row>
	      <entry><option>%N</option></entry>
	      <entry>Job number [N]</entry>
	    </row>
	    <row>
	      <entry><option>%S</option></entry>
	      <entry>Invocation (command line) of job begins with string <emphasis>S</emphasis></entry>
	    </row>
	    <row>
	      <entry><option>%?S</option></entry>
	      <entry>Invocation (command line) of job contains within it string <emphasis>S</emphasis></entry>
	    </row>
	    <row>
	      <entry><option>%%</option></entry>
	      <entry><quote>current</quote> job (last job stopped in
	      foreground or started in background)</entry>
	    </row>
	    <row>
	      <entry><option>%+</option></entry>
	      <entry><quote>current</quote> job (last job stopped in
	      foreground or started in background)</entry>
	    </row>
	    <row>
	      <entry><option>%-</option></entry>
	      <entry>Last job</entry>
	    </row>
	    <row>
	      <entry><option>$!</option></entry>
	      <entry>Last background process</entry>
	    </row>
	  </tbody>
	</tgroup>
      </table>

      </sect1> <!-- Job Control Commands -->

  </chapter> <!-- Internal Commands and Builtins -->



  <chapter id="external">
      <title>External Filters, Programs and Commands</title>

      <para><anchor id="externalref"></para>

      <para>Standard UNIX commands make shell scripts more versatile. The
	power of scripts comes from coupling system commands and shell
	directives with simple programming constructs.</para>

      <sect1 id="basic">
        <title>Basic Commands</title>

      <variablelist id="basiccommands">
        <title><anchor id="basiccommands1">The first commands a novice learns</title>

	<varlistentry>
	  <term><anchor id="lsref"><command>ls</command></term>
	  <indexterm>
	    <primary>ls</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>ls</secondary>
	  </indexterm>
	  <listitem>
	    <para>The basic file <quote>list</quote> command. It is all too easy
	      to underestimate the power of this humble command. For
	      example, using the <option>-R</option>, recursive option,
	      <command>ls</command> provides a tree-like listing of
	      a directory structure. Other interesting options are
	      <option>-S</option>, sort listing by file size,
	      <option>-t</option>, sort by file modification time, and
	      <option>-i</option>, show file inodes (see <xref
	      linkend="idelete">).</para>

	    <example id="ex40">
	      <title>Using <command>ls</command> to create a table of contents
		for burning a <abbrev>CDR</abbrev> disk</title>
	      <programlisting>&ex40;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="catref"><command>cat</command></term>
	  <term><command>tac</command></term>
	  <indexterm>
	    <primary>cat</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cat</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>tac</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tac</secondary>
	  </indexterm>
	  <listitem>
	    <para><command>cat</command>, an acronym for
	    <wordasword>concatenate</wordasword>,
	      lists a file to <filename>stdout</filename>. When
	      combined with redirection (<token>></token> or
	      <token>>></token>), it is commonly used to concatenate
	      files.

	        <programlisting>cat filename cat file.1 file.2 file.3 &gt; file.123</programlisting>

	      The <option>-n</option> option to <command>cat</command>
	      inserts consecutive numbers before all lines of the
	      target file(s). The <option>-b</option> option numbers
	      only the non-blank lines. The <option>-v</option> option
	      echoes nonprintable characters, using <token>^</token>
	      notation. The <option>-s</option> option squeezes multiple
	      consecutive blank lines into a single blank line.</para>

            <para>See also <xref linkend="lnum"> and <xref linkend="rot13">.</para>

	    <para><command>tac</command>, is the inverse of
	      <wordasword>cat</wordasword>, listing a file backwards from its end.</para>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>rev</command></term>
	  <indexterm>
	    <primary>rev</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>rev</secondary>
	  </indexterm>
	  <listitem>
	    <para>reverses each line of a file, and outputs to
	      <filename>stdout</filename>.  This is not the same effect
	      as <command>tac</command>, as it preserves the order of
	      the lines, but flips each one around.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>cat file1.txt</userinput>
<computeroutput>This is line 1.
 This is line 2.</computeroutput>


<prompt>bash$ </prompt><userinput>tac file1.txt</userinput>
<computeroutput>This is line 2.
 This is line 1.</computeroutput>


<prompt>bash$ </prompt><userinput>rev file1.txt</userinput>
<computeroutput>.1 enil si sihT
 .2 enil si sihT</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>cp</command></term>
	  <indexterm>
	    <primary>cp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cp</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is the file copy command. <userinput>cp file1
	      file2</userinput> copies <filename>file1</filename>
	      to <filename>file2</filename>, overwriting
	      <filename>file2</filename> if it already exists (see <xref
	      linkend="ex42">).</para>

	     <tip><para>Particularly useful are the <option>-a</option>
	       archive flag (for copying an entire directory tree)
	       and the <option>-r</option> and <option>-R</option>
	       recursive flags.</para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>mv</command></term>
	  <listitem>
	    <para>This is the file <emphasis>move</emphasis> command. It
	      is equivalent to a combination of <command>cp</command>
	      and <command>rm</command>. It may be used to move multiple
	      files to a directory, or even to rename a directory. For
	      some examples of using <command>mv</command> in a script,
	      see <xref linkend="rfe"> and <xref linkend="rn">.</para>

	    <note>
	    <para>When used in a non-interactive script,
	      <command>mv</command> takes the <option>-f</option>
	      (<emphasis>force</emphasis>) option to bypass user
	      input.</para>

	    <para>When a directory is moved to a preexisting directory,
	      it becomes a subdirectory of the destination directory.</para>
	  <para>
	      <screen>
<prompt>bash$ </prompt><userinput>mv source_directory target_directory</userinput>

<prompt>bash$ </prompt><userinput>ls -lF target_directory</userinput>
<computeroutput>total 1
 drwxrwxr-x    2 bozo  bozo      1024 May 28 19:20 source_directory/</computeroutput>
	      </screen>
	    </para>
	    </note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>rm</command></term>
	  <indexterm>
	    <primary>rm</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>rm</secondary>
	  </indexterm>
	  <listitem>
	    <para>Delete (remove) a file or files. The <option>-f</option>
	      option forces removal of even readonly files, and is useful
	      for bypassing user input in a script.</para>

	    <warning><para>When used with the recursive flag
	      <option>-r</option>, this command removes files all the way
	      down the directory tree.</para></warning>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>rmdir</command></term>
	  <indexterm>
	    <primary>rmdir</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>rmdir</secondary>
	  </indexterm>
	  <listitem>
	    <para>Remove directory. The directory must be empty of
	      all files, including <anchor id="dotfilesref"> invisible
	      <quote>dotfiles</quote>,

		<footnote><para>These are files whose names begin with
		  a dot, such as <filename>~/.Xdefaults</filename>. Such
		  filenames do not show up in a normal
		  <command>ls</command> listing, and they cannot
		  be deleted by an accidental <command>rm -rf
		  *</command>. Dotfiles are generally used as
		  setup and configuration files in a user's home
		  directory.</para></footnote>

	      for this command to succeed.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>mkdir</command></term>
	  <indexterm>
	    <primary>mkdir</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>mkdir</secondary>
	  </indexterm>
	  <listitem>
	    <para>Make directory, creates a new directory.
	      <userinput>mkdir -p project/programs/December</userinput>
	      creates the named directory. The
	      <replaceable>-p</replaceable> option automatically creates
	      any necessary parent directories.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="chmodref"><command>chmod</command></term>
	  <indexterm>
	    <primary>chmod</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>chmod</secondary>
	  </indexterm>
	  <listitem>

	    <para>Changes the attributes of an existing file (see <xref
	      linkend="ex44">).</para>

	    <para><programlisting>chmod +x filename
# Makes "filename" executable for all users.

chmod u+s filename
# Sets "suid" bit on "filename" permissions.
# An ordinary user may execute "filename" with same privileges as the file's owner.
# (This does not apply to shell scripts.)</programlisting></para>

	    <para><programlisting>chmod 644 filename
# Makes "filename" readable/writable to owner, readable to
# others
# (octal mode).</programlisting></para>

	    <para><programlisting>chmod 1777 directory-name
# Gives everyone read, write, and execute permission in directory,
# however also sets the "sticky bit".
# This means that only the owner of the directory,
# owner of the file, and, of course, root
# can delete any particular file in that directory.</programlisting></para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>chattr</command></term>
	  <indexterm>
	    <primary>chattr</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>chattr</secondary>
	  </indexterm>
	  <listitem>
	    <para>Change file attributes. This has the same effect
	      as <command>chmod</command> above, but with a
	      different invocation syntax, and it works only on an
	      <emphasis>ext2</emphasis> filesystem.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>ln</command></term>
	  <listitem>

	    <para>Creates links to pre-existings files. Most often used
	      with the <option>-s</option>, symbolic or
	      <quote>soft</quote> link flag. This permits referencing
	      the linked file by more than one name and is a superior
	      alternative to aliasing (see <xref linkend="ex18">).</para>

	    <para><userinput>ln -s oldfile newfile</userinput>
	      links the previously existing
	      <filename>oldfile</filename> to the newly created link,
	      <filename>newfile</filename>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>man</command></term>
	  <term><command>info</command></term>
	  <indexterm>
	    <primary>man</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>man</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>info</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>info</secondary>
	  </indexterm>
	  <listitem>

	    <para>These commands access the manual and information pages on
	      system commands and installed utilities. When available, the
	      <emphasis>info</emphasis> pages usually contain a more detailed
	      description than do the <emphasis>man</emphasis> pages.</para>

	  </listitem>
	</varlistentry>


      </variablelist>


        </sect1> <!-- End Basic Commands -->


      <sect1 id="moreadv">
        <title>Complex Commands</title>

      <variablelist id="cclisting">
        <title><anchor id="cclisting1">Commands for more advanced users</title>

	<varlistentry>
	  <term><anchor id="findref"><command>find</command></term>
	  <indexterm>
	    <primary>find</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>find</secondary>
	  </indexterm>

	  <indexterm>
	    <primary>{}</primary>
	  </indexterm>
	  <indexterm>
	    <primary>special character</primary>
	    <secondary>{}</secondary>
	  </indexterm>

	  <indexterm>
	    <primary>\;</primary>
	  </indexterm>
	  <indexterm>
	    <primary>escaped character</primary>
	    <secondary>\;</secondary>
	  </indexterm>

	  <listitem>
	    <para>-exec <replaceable>COMMAND</replaceable> \;</para>
	    <para>Carries out <replaceable>COMMAND</replaceable> on
	      each file that <command>find</command> matches.
	      The command sequence terminates with <token>\;</token>
	      (the <quote>;</quote> is escaped to make certain
	      the shell passes it to <command>find</command>
	      literally).  If <replaceable>COMMAND</replaceable>
	      contains <token>{}</token>, then <command>find</command>
	      substitutes the full path name of the selected file for
	      <quote>{}</quote>.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>find ~/ -name '*.txt'</userinput>
<computeroutput>/home/bozo/.kde/share/apps/karm/karmdata.txt
 /home/bozo/misc/irmeyc.txt
 /home/bozo/test-scripts/1.txt</computeroutput>
	      </screen>
	  </para>

	  <para>
	  <programlisting>find /home/bozo/projects -mtime 1
#  Lists all files in /home/bozo/projects directory tree
#+ that were modified within the last day.
#
#  mtime = last modification time of the target file
#  ctime = last status change time (via 'chmod' or otherwise)
#  atime = last access time

DIR=/home/bozo/junk_files
find "$DIR" -type f -atime +5 -exec rm {} \;
#  Deletes all files in "/home/bozo/junk_files"
#+ that have not been accessed in at least 5 days.
#
#  "-type filetype", where
#  f = regular file
#  d = directory, etc.
#  (The 'find' manpage has a complete listing.)</programlisting>
          </para>



	    <para><programlisting>find /etc -exec grep '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*' {} \;

# Finds all IP addresses (xxx.xxx.xxx.xxx) in /etc directory files.
# There a few extraneous hits - how can they be filtered out?

# Perhaps by:

find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \
 | grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$'
# [:digit:] is one of the character classes
# introduced with the POSIX 1003.2 standard. 

# Thanks, S.C. 
</programlisting></para>


            <note><para>The <option>-exec</option> option to
	      <command>find</command> should not be confused with the <link
	      linkend="execref">exec</link> shell builtin.</para></note>

	    <example id="ex57">
	      <title><command>Badname</command>, eliminate file names
		in current directory containing bad characters and <link
		linkend="whitespaceref">whitespace</link>.</title>
	      <programlisting>&ex57;</programlisting>
	    </example>

	    <example id="idelete">
	      <title>Deleting a file by its <emphasis>inode</emphasis>
	        number</title>
	      <programlisting>&idelete;</programlisting>
	    </example>

	    <para>See <xref linkend="ex48">, <xref linkend="ex58">,
	      and <xref linkend="findstring"> for scripts using
	      <command>find</command>. Its manpage provides more detail
	      on this complex and powerful command.</para>


	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>xargs</command></term>
	  <indexterm>
	    <primary>xargs</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>xargs</secondary>
	  </indexterm>
	  <listitem>
	    <para>A filter for feeding arguments to a command, and also
	      a tool for assembling the commands themselves. It breaks
	      a data stream into small enough chunks for filters
	      and commands to process.	Consider it as a powerful
	      replacement for backquotes.  In situations where backquotes
	      fail with a <errorname>too many arguments</errorname>
	      error, substituting <command>xargs</command> often
	      works. Normally, <command>xargs</command> reads from
	      <filename>stdin</filename> or from a pipe, but it can also
	      be given the output of a file.</para>

	    <para>The default command for <command>xargs</command> is
	      <link linkend="echoref">echo</link>. This means that input
	      piped to <command>xargs</command> may have linefeeds and
	      other whitespace characters stripped out.
	      
	      <screen>
<prompt>bash$ </prompt><userinput>ls -l</userinput>
<computeroutput>total 0
 -rw-rw-r--    1 bozo  bozo         0 Jan 29 23:58 file1
 -rw-rw-r--    1 bozo  bozo         0 Jan 29 23:58 file2</computeroutput>


<prompt>bash$ </prompt><userinput>ls -l | xargs</userinput>
<computeroutput>total 0 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2</computeroutput>
	      </screen>
	      
	      </para>

	    <para><userinput>ls | xargs -p -l gzip</userinput> <link
	      linkend="gzipref">gzips</link> every file in current
	      directory, one at a time, prompting before each
	      operation.</para>

	    <tip>
	    <para>An interesting <command>xargs</command>
	      option is <option>-n <replaceable>NN</replaceable></option>,
	      which limits to <replaceable>NN</replaceable> the number
	      of arguments passed.</para>
	    <para><userinput>ls | xargs -n 8 echo</userinput> lists the files in the
	      current directory in <literal>8</literal> columns.</para>
	    </tip>  
	      
	      
	    <tip>
	    <para>Another useful option is
	      <option>-0</option>, in combination with <command>find
	      -print0</command> or <command>grep -lZ</command>. This
	      allows handling arguments containing whitespace or
	      quotes.</para>
	      
	    <para>
	    <userinput>find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f</userinput>
	    </para>
	    
	    <para>
	    <userinput>grep -rliwZ GUI / | xargs -0 rm -f</userinput>
	    </para>

	    <para>Either of the above will remove any file containing <quote>GUI</quote>.
	      <emphasis>(Thanks, S.C.)</emphasis></para>
	    </tip>




	    <example id="ex41">
	      <title>Logfile using <command>xargs</command> to monitor system log</title>
	      <programlisting>&ex41;</programlisting>
	    </example>	    

	    <example id="ex42">
	      <title><command>copydir</command>, copying files in current
		directory to another, using <command>xargs</command></title>
	      <programlisting>&ex42;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="exprref"><userinput>expr</userinput></term>
	  <indexterm>
	    <primary>expr</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>expr</secondary>
	  </indexterm>
	  <listitem>
	    <para>All-purpose expression evaluator:
	      Concatenates and evaluates the arguments according
	      to the operation given (arguments must be separated
	      by spaces). Operations may be arithmetic, comparison,
	      string, or logical.</para>

	    <variablelist>
	      <varlistentry>
		<term><userinput>expr 3 + 5</userinput></term>
		<listitem>
		  <para>returns <literal>8</literal></para>
		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>expr 5 % 3</userinput></term>
		<listitem>
		  <para>returns 2</para>
		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>expr 5 \* 3</userinput></term>
		<listitem>
		<para>returns 15</para>
		<para>The multiplication operator
		  must be escaped when used in an arithmetic expression
		  with <command>expr</command>.</para>
		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><userinput>y=`expr $y + 1`</userinput></term>
		<listitem>
		  <para>Increment a variable, with the same effect
		    as <userinput>let y=y+1</userinput> and
		    <userinput>y=$(($y+1))</userinput>. This is an
		    example of <link linkend="arithexpref">arithmetic
		    expansion</link>.</para>
		</listitem>
	      </varlistentry>

	      <varlistentry>
		<term><anchor id="expextrsub"><userinput>z=`expr substr
		$string $position $length`</userinput></term>
		<listitem>
		  <para>Extract substring of $length characters, starting
		    at $position.</para>
		</listitem>
	      </varlistentry>
	    </variablelist>

	    <example id="ex45">
	      <title>Using <command>expr</command></title>
	      <programlisting>&ex45;</programlisting>
	    </example>	    
	    
	    <important>
	    <para>The <link linkend="nullref">:</link> operator
	      can substitute for <command>match</command>. For example,
	      <userinput>b=`expr $a : [0-9]*`</userinput> is the
	      exact equivalent of <userinput>b=`expr match $a
	      [0-9]*`</userinput> in the above listing.</para>

	    <para><programlisting>&ex45a;</programlisting></para>
	      </important>

	  </listitem>
	</varlistentry>

       </variablelist>

	    <para>This example illustrates how
	      <command>expr</command> uses the <emphasis>escaped
	      parentheses -- \( ... \) --</emphasis> grouping operator
	      in tandem with <link linkend="regexref">regular
	      expression</link> parsing to match a substring.</para>


            <para><link linkend="perlref">Perl</link>,
	      <link linkend="sedref">sed</link>, and <link
	      linkend="awkref">awk</link> have far superior string
	      parsing facilities.  A short <command>sed</command> or
	      <command>awk</command> <quote>subroutine</quote> within
	      a script (see <xref linkend="wrapper">) is an attractive
	      alternative to using <command>expr</command>.</para>


            <para>See <xref linkend="String-Manipulation"> for more on
              string operations.</para>


	</sect1> <!-- End Complex Commands -->



      <sect1 id="timedate">
        <title>Time / Date Commands</title>

       <variablelist id="tdlisting">
         <title><anchor id="tdlisting1">Time/date and timing</title>

	<varlistentry>
	  <term><anchor id="dateref"><command>date</command></term>
	  <indexterm>
	    <primary>date</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>date</secondary>
	  </indexterm>
	  <listitem>
	    <para>Simply invoked, <command>date</command> prints the date and
	      time to <filename>stdout</filename>. Where this command gets
	      interesting is in its formatting and parsing options.</para>

	    <example id="ex51">
	      <title>Using <command>date</command></title>
	      <programlisting>&ex51;</programlisting>
	    </example>	    	   

	    <para>The <option>-u</option> option gives the UTC (Universal
	      Coordinated Time).</para>

	      <para>
	      <screen>
<prompt>bash$ </prompt><userinput>date</userinput>
<computeroutput>Fri Mar 29 21:07:39 MST 2002</computeroutput>



<prompt>bash$ </prompt><userinput>date -u</userinput>
<computeroutput>Sat Mar 30 04:07:42 UTC 2002</computeroutput>
	      </screen>
	      </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>zdump</command></term>
	  <indexterm>
	    <primary>zdump</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>time zone dump</secondary>
	  </indexterm>
	  <listitem>
	    <para>Echoes the time in a specified time zone.</para>
	      <para>
	      <screen><prompt>bash$ </prompt><userinput>zdump EST</userinput>
<computeroutput>EST  Tue Sep 18 22:09:22 2001 EST</computeroutput>
	      </screen>
	      </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="timref"><command>time</command></term>
	  <indexterm>
	    <primary>time</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>time</secondary>
	  </indexterm>
	  <listitem>

	    <para>Outputs very verbose timing statistics for executing a command.</para>

	    <para><userinput>time ls -l /</userinput> gives something like this:
<screen><computeroutput>0.00user 0.01system 0:00.05elapsed 16%CPU (0avgtext+0avgdata 0maxresident)k
 0inputs+0outputs (149major+27minor)pagefaults 0swaps</computeroutput></screen>
	  </para>

	  <para>See also the very similar <link
	    linkend="timesref">times</link> command in the previous
	    section.</para>

	  <note><para>As of <link linkend="bash2ref">version 2.0</link>
	    of Bash, <command>time</command> became a shell reserved word,
	    with slightly altered behavior in a pipeline.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="touchref"><command>touch</command></term>
	  <indexterm>
	    <primary>touch</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>touch</secondary>
	  </indexterm>
	  <listitem>

	    <para>Utility for updating access/modification times of a
	      file to current system time or other specified time,
	      but also useful for creating a new file. The command
	      <userinput>touch zzz</userinput> will create a new file
	      of zero length, named <filename>zzz</filename>, assuming
	      that <filename>zzz</filename> did not previously exist.
	      Time-stamping empty files in this way is useful for
	      storing date information, for example in keeping track of
	      modification times on a project.
	      </para>

	    <note><para>The <command>touch</command> command is
	      equivalent to <userinput>: &gt;&gt; newfile</userinput>
	      or <userinput>&gt;&gt; newfile</userinput> (for ordinary
	      files).</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="atref"><command>at</command></term>
	  <indexterm>
	    <primary>at</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>at</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>crond</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>crond</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>at</command> job control command executes
	      a given set of commands at a specified time. Superficially,
	      it resembles <link linkend="cronref">crond</link>, however,
	      <command>at</command> is chiefly useful for one-time execution
	      of a command set.</para>
	  
	    <para><userinput>at 2pm January 15</userinput> prompts for a set of
	      commands to execute at that time. These commands should be
	      shell-script compatible, since, for all practical
	      purposes, the user is typing in an executable shell
	      script a line at a time.	Input terminates with a <link
	      linkend="ctldref">Ctl-D</link>.</para>

	    <para>Using either the <option>-f</option> option or input
	      redirection (<token><</token>), <command>at</command>
	      reads a command list from a file. This file is an
	      executable shell script, though it should, of course,
	      be noninteractive. Particularly clever is including the
	      <link linkend="runpartsref">run-parts</link> command in
	      the file to execute a different set of scripts.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>at 2:30 am Friday < at-jobs.list</userinput>
<computeroutput>job 2 at 2000-10-27 02:30</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>batch</command></term>
	  <indexterm>
	    <primary>batch</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>batch</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>at</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>at</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>batch</command> job control command is similar to
	      <command>at</command>, but it runs a command list when the system
	      load drops below <literal>.8</literal>. Like
	      <command>at</command>, it can read commands from a file with the
	      <option>-f</option> option.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>cal</command></term>
	  <indexterm>
	    <primary>cal</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cal</secondary>
	  </indexterm>
	  <listitem>
	    <para>Prints a neatly formatted monthly calendar to
	      <filename>stdout</filename>. Will do current year or a large
	      range of past and future years.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sleep</command></term>
	  <indexterm>
	    <primary>sleep</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sleep</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is the shell equivalent of a wait loop. It pauses for a
	      specified number of seconds, doing nothing. It can be useful
	      for timing or in processes running in the background,
	      checking for a specific event every so often (polling),
	      as in <xref linkend="online">.
	      <programlisting>sleep 3
# Pauses 3 seconds.</programlisting>
	    </para>

	    <note><para>The <command>sleep</command> command defaults to
	      seconds, but minute, hours, or days may also be specified.
	      <programlisting>sleep 3 h
# Pauses 3 hours!</programlisting>
            </para></note>

	    <note><para>The <link linkend="watchref">watch</link> command may
	      be a better choice than <command>sleep</command> for running
	      commands at timed intervals.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>usleep</command></term>
	  <indexterm>
	    <primary>usleep</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>usleep</secondary>
	  </indexterm>
	  <listitem>
	    <para><emphasis>Microsleep</emphasis> (the <quote>u</quote>
	      may be read as the Greek <quote>mu</quote>, or micro-
	      prefix). This is the same as <command>sleep</command>,
	      above, but <quote>sleeps</quote> in microsecond
	      intervals. It can be used for fine-grain timing, or for
	      polling an ongoing process at very frequent intervals.</para>

	    <para>  
	      <programlisting>usleep 30
# Pauses 30 microseconds.</programlisting>
	    </para>

	    <para>This command is part of the Red Hat <emphasis>initscripts /
	      rc-scripts</emphasis> package.</para>

	    <caution><para>The <command>usleep</command> command does not
	      provide particularly accurate timing, and is therefore
	      unsuitable for critical timing loops.</para></caution>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>hwclock</command></term>
	  <term><command>clock</command></term>
	  <indexterm>
	    <primary>hwclock</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>hwclock</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>clock</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>clock</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>hwclock</command> command accesses or
	      adjusts the machine's hardware clock. Some
	      options require root privileges. The
	      <filename>/etc/rc.d/rc.sysinit</filename> startup file
	      uses <command>hwclock</command> to set the system time
	      from the hardware clock at bootup.</para>

	    <para>The <command>clock</command> command is a synonym for
	      <command>hwclock</command>.</para>
	  </listitem>
	</varlistentry>


       </variablelist>
       
        </sect1> <!-- End Time / Date Commands -->




      <sect1 id="textproc">
        <title>Text Processing Commands</title>

       <variablelist id="tpcommandlisting">
         <title><anchor id="tpcommandlisting1">Commands affecting text and
	   text files</title>

	<varlistentry>
	  <term><anchor id="sortref"><command>sort</command></term>
	  <indexterm>
	    <primary>sort</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sort</secondary>
	  </indexterm>
	  <listitem>
	    <para>File sorter, often used as a filter in a pipe. This
	      command sorts a text stream or file forwards or backwards,
	      or according to various keys or character positions. Using
	      the <option>-m</option> option, it merges presorted input
	      files.  The <emphasis>info page</emphasis> lists its many
	      capabilities and options. See <xref linkend="findstring">,
	      <xref linkend="symlinks">, and <xref linkend="makedict">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>tsort</command></term>
	  <indexterm>
	    <primary>tsort</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>topological sort</secondary>
	  </indexterm>
	  <listitem>
	    <para>Topological sort, reading in pairs of
	      whitespace-separated strings and sorting according to
	      input patterns.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="uniqref"><command>uniq</command></term>
	  <indexterm>
	    <primary>uniq</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uniq</secondary>
	  </indexterm>
	  <listitem>
	    <para>This filter removes duplicate lines from a sorted
	      file. It is often seen in a pipe coupled with
	      <link linkend="sortref">sort</link>.
	      <programlisting>cat list-1 list-2 list-3 | sort | uniq > final.list
# Concatenates the list files,
# sorts them,
# removes duplicate lines,
# and finally writes the result to an output file.</programlisting></para>
 
             <para>The useful <option>-c</option> option prefixes each line of
	       the input file with its number of occurrences.</para>
	     <para>
	      <screen>
<prompt>bash$ </prompt><userinput>cat testfile</userinput>
<computeroutput>This line occurs only once.
 This line occurs twice.
 This line occurs twice.
 This line occurs three times.
 This line occurs three times.
 This line occurs three times.</computeroutput>


<prompt>bash$ </prompt><userinput>uniq -c testfile</userinput>
<computeroutput>      1 This line occurs only once.
       2 This line occurs twice.
       3 This line occurs three times.</computeroutput>


<prompt>bash$ </prompt><userinput>sort testfile | uniq -c | sort -nr</userinput>
<computeroutput>      3 This line occurs three times.
       2 This line occurs twice.
       1 This line occurs only once.</computeroutput>
	      </screen>
	     </para>

	     <para>The <userinput>sort INPUTFILE | uniq -c | sort -nr</userinput>
	       command string produces a <emphasis>frequency
	       of occurrence</emphasis> listing on the
	       <filename>INPUTFILE</filename> file (the
	       <option>-nr</option> options to <command>sort</command>
	       cause a reverse numerical sort). This template finds
	       use in analysis of log files and dictionary lists, and
	       wherever the lexical structure of a document needs to
	       be examined.</para>

	    <example id="wf">
	      <title>Word Frequency Analysis</title>
	      <programlisting>&wf;</programlisting>
	    </example>	    

	     <para>
	       <screen>
<prompt>bash$ </prompt><userinput>cat testfile</userinput>
<computeroutput>This line occurs only once.
 This line occurs twice.
 This line occurs twice.
 This line occurs three times.
 This line occurs three times.
 This line occurs three times.</computeroutput>


<prompt>bash$ </prompt><userinput>./wf.sh testfile</userinput>
<computeroutput>      6 this
       6 occurs
       6 line
       3 times
       3 three
       2 twice
       1 only
       1 once</computeroutput>
	       </screen>
	     </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="expandref"><command>expand</command></term>
	  <term><command>unexpand</command></term>
	  <indexterm>
	    <primary>expand</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>expand</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>unexpand</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>unexpand</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>expand</command> filter converts tabs to
	      spaces. It is often used in a pipe.</para>
	    <para>The <command>unexpand</command> filter
	      converts spaces to tabs. This reverses the effect of
	      <command>expand</command>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="cutref"><command>cut</command></term>
	  <indexterm>
	    <primary>cut</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cut</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>awk</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>awk</secondary>
	  </indexterm>
	  <listitem>
	    <para>A tool for extracting fields from files. It is similar to the 
	      <userinput>print $N</userinput> command set in <link
	      linkend="awkref">awk</link>, but more limited. It may be
	      simpler to use <command>cut</command> in a script than
	      <command>awk</command>. Particularly important are the
	      <option>-d</option> (delimiter) and <option>-f</option>
	      (field specifier) options.</para>

	    <para>Using <command>cut</command> to obtain a listing of the
	      mounted filesystems: 
	      <programlisting>cat /etc/mtab | cut -d ' ' -f1,2</programlisting></para>

	    <para>Using <command>cut</command> to list the OS and kernel version:
	      <programlisting>uname -a | cut -d" " -f1,3,11,12</programlisting></para>

	    <para>Using <command>cut</command> to extract message headers from
	      an e-mail folder:

	      <screen><prompt>bash$ </prompt><userinput>grep '^Subject:' read-messages | cut -c10-80</userinput>
<computeroutput>Re: Linux suitable for mission-critical apps?
 MAKE MILLIONS WORKING AT HOME!!!
 Spam complaint
 Re: Spam complaint</computeroutput></screen>
	    </para>

	    <para>Using <command>cut</command> to parse a file:
	      <programlisting># List all the users in /etc/passwd.

FILENAME=/etc/passwd

for user in $(cut -d: -f1 $FILENAME)
do
  echo $user
done

# Thanks, Oleg Philon for suggesting this.</programlisting></para>

	    <para><userinput>cut -d ' ' -f2,3 filename</userinput> is equivalent to
	      <userinput>awk -F'[ ]' '{ print $2, $3 }' filename</userinput></para>

	    <para>See also <xref linkend="base">.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>paste</command></term>
	  <indexterm>
	    <primary>paste</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>paste</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>cut</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cut</secondary>
	  </indexterm>
	  <listitem>
	    <para>Tool for merging together different files into a single,
	      multi-column file.  In combination with
	      <command>cut</command>, useful for creating system log
	      files.
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>join</command></term>
	  <indexterm>
	    <primary>join</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>join</secondary>
	  </indexterm>
	  <listitem>
	    <para>Consider this a special-purpose cousin of
	      <command>paste</command>. This powerful utility allows
	      merging two files in a meaningful fashion, which essentially
	      creates a simple version of a relational database.</para>

	    <para>The <command>join</command> command operates on
	      exactly two files, but pastes together only those lines
	      with a common tagged field (usually a numerical label),
	      and writes the result to <filename>stdout</filename>.
	      The files to be joined should be sorted according to the
	      tagged field for the matchups to work properly.</para>

	      <para><programlisting>File: 1.data

100 Shoes
200 Laces
300 Socks</programlisting></para>
      
              <para><programlisting>File: 2.data

100 $40.00
200 $1.00
300 $2.00</programlisting></para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>join 1.data 2.data</userinput>
<computeroutput>File: 1.data 2.data

 100 Shoes $40.00
 200 Laces $1.00
 300 Socks $2.00</computeroutput>
	      </screen>
	    </para>

	    <note><para>The tagged field appears only once in the
	      output.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>head</command></term>
	  <indexterm>
	    <primary>head</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>head</secondary>
	  </indexterm>
	  <listitem>
	    <para>lists the beginning of a file to
	      <filename>stdout</filename> (the default is
	      <literal>10</literal> lines, but this can be changed). It
	      has a number of interesting options.

	    <example id="scriptdetector">
	      <title>Which files are scripts?</title>
	      <programlisting>&scriptdetector;</programlisting>
	    </example>	    

	    <example id="rnd">
	      <title>Generating 10-digit random numbers</title>
	      <programlisting>&rnd;</programlisting>
	    </example>	    

	      See also <xref linkend="ex52">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>tail</command></term>
	  <indexterm>
	    <primary>tail</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tail</secondary>
	  </indexterm>
	  <listitem>
	    <para>lists the end of a file to <filename>stdout</filename>
	      (the default is <literal>10</literal> lines).  Commonly used
	      to keep track of changes to a system logfile, using the
	      <option>-f</option> option, which outputs lines appended
	      to the file.</para>

	   <example id="ex12">
	     <title>Using <command>tail</command> to monitor the system log</title>
	     <programlisting>&ex12;</programlisting>
	   </example>

	      <para>See also <xref linkend="ex41">, <xref linkend="ex52"> and
		<xref linkend="online">.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="grepref"><command>grep</command></term>
	  <indexterm>
	    <primary>grep</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>grep</secondary>
	  </indexterm>
	  <listitem>
	    <para>A multi-purpose file search tool that uses
	      <link linkend="regexref">regular expressions</link>.
	      It was originally a command/filter in the
	      venerable <command>ed</command> line editor,
	      <userinput>g/re/p</userinput>, that is, <emphasis>global -
	      regular expression - print</emphasis>.</para>

	    <para><cmdsynopsis>
		<command>grep</command> <arg
		choice="plain"><replaceable>pattern</replaceable></arg>
		<arg choice="opt"
		rep="repeat"><replaceable>file</replaceable></arg>
	      </cmdsynopsis>Search the target file(s) for
	      occurrences of <replaceable>pattern</replaceable>, where
	      <replaceable>pattern</replaceable> may be literal text
	      or a regular expression.</para>

	      <para>
	      <screen><prompt>bash$ </prompt><userinput>grep '[rst]ystem.$' osinfo.txt</userinput>
<computeroutput>The GPL governs the distribution of the Linux operating system.</computeroutput>
	      </screen>
	      </para>

	    <para>If no target file(s) specified, <command>grep</command>
	      works as a filter on <filename>stdout</filename>, as in
	      a <link linkend="piperef">pipe</link>.</para>

	      <para>
	      <screen><prompt>bash$ </prompt><userinput>ps ax | grep clock</userinput>
<computeroutput>765 tty1     S      0:00 xclock
 901 pts/1    S      0:00 grep clock</computeroutput>
	      </screen>
	      </para>

	    <para>The <option>-i</option> option causes a case-insensitive
	      search.</para>

	    <para>The <option>-w</option> option matches only whole
	      words.</para>

	    <para>The <option>-l</option> option lists only the files in which
	      matches were found, but not the matching lines.</para>

	    <para>The <option>-r</option> (recursive) option searches files in
	      the current working directory and all subdirectories below
	      it.</para>

	    <para>The <option>-n</option> option lists the matching lines,
	      together with line numbers.</para>

	      <para>
	      <screen><prompt>bash$ </prompt><userinput>grep -n Linux osinfo.txt</userinput>
<computeroutput>2:This is a file containing information about Linux.
 6:The GPL governs the distribution of the Linux operating system.</computeroutput>
	      </screen>
	      </para>

	    <para>The <option>-v</option> (or <option>--invert-match</option>)
	      option <emphasis>filters out</emphasis> matches.
	      <programlisting>grep pattern1 *.txt | grep -v pattern2

# Matches all lines in "*.txt" files containing "pattern1",
# but ***not*** "pattern2".	      
</programlisting></para>

	    <para>The <option>-c</option> (<option>--count</option>)
	      option gives a numerical count of matches, rather than
	      actually listing the matches.

	        <programlisting>grep -c txt *.sgml   # (number of occurrences of "txt" in "*.sgml" files)


#   grep -cz .
#            ^ dot
# means count (-c) zero-separated (-z) items matching "."
# that is, non-empty ones (containing at least 1 character).
# 
printf 'a b\nc  d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz .     # 4
printf 'a b\nc  d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '$'   # 5
printf 'a b\nc  d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '^'   # 5
#
printf 'a b\nc  d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -c '$'    # 9
# By default, newline chars (\n) separate items to match. 

# Note that the -z option is GNU "grep" specific.


# Thanks, S.C.</programlisting>
            </para>

	    <para>When invoked with more than one target file given,
	      <command>grep</command> specifies which file contains
	      matches.</para>

	    <para>
	      <screen><prompt>bash$ </prompt><userinput>grep Linux osinfo.txt misc.txt</userinput>
<computeroutput>osinfo.txt:This is a file containing information about Linux.
 osinfo.txt:The GPL governs the distribution of the Linux operating system.
 misc.txt:The Linux operating system is steadily gaining in popularity.</computeroutput>
	      </screen>
	    </para>


	    <tip>
	    <para>To force <command>grep</command> to show the filename
	      when searching only one target file, simply give
	      <filename>/dev/null</filename> as the second file.</para>
	    <para>
	      <screen><prompt>bash$ </prompt><userinput>grep Linux osinfo.txt /dev/null</userinput>
<computeroutput>osinfo.txt:This is a file containing information about Linux.
 osinfo.txt:The GPL governs the distribution of the Linux operating system.</computeroutput>
	      </screen>
	    </para>
	    </tip>


	    <para>If there is a successful match, <command>grep</command>
	      returns an <link linkend="exitstatusref">exit status</link>
	      of 0, which makes it useful in a condition test in a
	      script, especially in combination with the <option>-q</option>
	      option to suppress output.
	        <programlisting>SUCCESS=0                      # if grep lookup succeeds
word=Linux
filename=data.file

grep -q "$word" "$filename"    # The "-q" option causes nothing to echo to stdout.

if [ $? -eq $SUCCESS ]
then
  echo "$word found in $filename"
else
  echo "$word not found in $filename"
fi</programlisting>
            </para>


	    <para><xref linkend="online"> demonstrates how to use
	      <command>grep</command> to search for a word pattern in
	      a system logfile.</para>


	    <example id="grp">
	      <title>Emulating <quote>grep</quote> in a script</title>
	      <programlisting>&grp;</programlisting>
	    </example>	    	   

	    <note>
	    <para><anchor id="egrepref"><command>egrep</command>
	      is the same as <command>grep -E</command>. This
	      uses a somewhat different, extended set of <link
	      linkend="regexref">regular expressions</link>, which can
	      make the search somewhat more flexible.</para>

	    <para><command>fgrep</command> is the same as <command>grep
	      -F</command>. It does a literal string search (no regular
	      expressions), which allegedly speeds things up a
	      bit.</para>
	      
	    <para><command>agrep</command> extends the capabilities of
	      <command>grep</command> to approximate matching. The search
	      string may differ by a specified number of characters from the
	      resulting matches. This utility is not part of the core Linux
	      distribution.</para>
	      
	      </note>
	    
	    <tip>
	    <para>To search compressed files, use
	      <command>zgrep</command>, <command>zegrep</command>,
	      or <command>zfgrep</command>. These also work
	      on non-compressed files, though slower than plain
	      <command>grep</command>, <command>egrep</command>,
	      <command>fgrep</command>.  They are handy for searching
	      through a mixed set of files, some compressed, some
	      not.</para>
	    <para>To search <link linkend="bzipref">bzipped</link>
	      files, use <command>bzgrep</command>.</para> </tip>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>look</command></term>
	  <indexterm>
	    <primary>look</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>look</secondary>
	  </indexterm>
	  <listitem>
	    <para>The command <command>look</command> works like
	      <command>grep</command>, but does a lookup on
	      a <quote>dictionary</quote>, a sorted word list.
	      By default, <command>look</command> searches for a match
	      in <filename>/usr/dict/words</filename>, but a different
	      dictionary file may be specified.</para>

	    <example id="lookup">
	      <title>Checking words in a list for validity</title>
	      <programlisting>&lookup;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>sed</command></term>
	  <term><command>awk</command></term>
	  <indexterm>
	    <primary>sed</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sed</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>awk</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>awk</secondary>
	  </indexterm>
	  <listitem>
	    <para>Scripting languages especially suited for parsing text
	      files and command output. May be embedded singly or in
	      combination in pipes and shell scripts.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command><link linkend="sedref">sed</link></command></term>
	  <listitem>
	    <para>Non-interactive <quote>stream editor</quote>, permits using
	      many <command>ex</command> commands in batch mode. It
	      finds many uses in shell scripts.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command><link linkend="awkref">awk</link></command></term>
	  <listitem>
	    <para>Programmable file extractor and formatter, good for
	      manipulating and/or extracting fields (columns) in
	      structured text files. Its syntax is similar to C.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>wc</command></term>
	  <indexterm>
	    <primary>wc</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>wc</secondary>
	  </indexterm>
	  <listitem>
	    <para><emphasis>wc</emphasis> gives a <quote>word count</quote> on a file or I/O stream:
	      <screen><prompt>bash $ </prompt><userinput>wc /usr/doc/sed-3.02/README</userinput>
<computeroutput>20     127     838 /usr/doc/sed-3.02/README</computeroutput>
[20 lines  127 words  838 characters]</screen></para>

	    <para><userinput>wc -w</userinput> gives only the word count.</para>
	    <para><userinput>wc -l</userinput> gives only the line count.</para>
	    <para><userinput>wc -c</userinput> gives only the character count.</para>
	    <para><userinput>wc -L</userinput> gives only the length of the longest line.</para>

            <para>Using <command>wc</command> to count how many
	    <emphasis>.txt</emphasis> files are in current working directory:
	      <programlisting>$ ls *.txt | wc -l
# Will work as long as none of the "*.txt" files have a linefeed in their name.

# Alternative ways of doing this are:
#      find . -maxdepth 1 -name \*.txt -print0 | grep -cz .
#      (shopt -s nullglob; set -- *.txt; echo $#)

# Thanks, S.C.</programlisting>
	    </para>

	    <para>Using <command>wc</command> to total up the size of all the
	      files whose names begin with letters in the range d - h
	      <screen><prompt>bash$ </prompt><userinput>wc [d-h]* | grep total | awk '{print $3}'</userinput>
<computeroutput>71832</computeroutput>
	      </screen>
	    </para>

	    <para>Using <command>wc</command> to count the instances of the
	      word <quote>Linux</quote> in the main source file for
	      this book.
	      <screen><prompt>bash$ </prompt><userinput>grep Linux abs-book.sgml | wc -l</userinput>
<computeroutput>50</computeroutput>
	      </screen>
	    </para>

	    <para>See also <xref linkend="ex52"> and <xref
	    linkend="redir4">.</para>

	    <para>Certain commands include some of the
	      functionality of <command>wc</command> as options.
	      
	    <programlisting>... | grep foo | wc -l
# This frequently used construct can be more concisely rendered.

... | grep -c foo
# Just use the "-c" (or "--count") option of grep.

# Thanks, S.C.</programlisting></para>

	  </listitem>
	</varlistentry>

	
	<varlistentry>
	  <term><anchor id="trref"><command>tr</command></term>
	  <indexterm>
	    <primary>tr</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tr</secondary>
	  </indexterm>
	  <listitem>
	    <para>character translation filter.</para>
	    
	    <caution><para><link linkend="ucref">Must use quoting and/or
	      brackets</link>, as appropriate. Quotes prevent the
	      shell from reinterpreting the special characters in
	      <command>tr</command> command sequences. Brackets should be
	      quoted to prevent expansion by the shell.  </para></caution>

	    <para>Either <userinput>tr "A-Z" "*" &lt;filename</userinput>
	      or <userinput>tr A-Z \* &lt;filename</userinput> changes
	      all the uppercase letters in <filename>filename</filename>
	      to asterisks (writes to <filename>stdout</filename>).
	      On some systems this may not work, but <userinput>tr A-Z
	      '[**]'</userinput> will.</para>

	    <para>The <option>-d</option> option deletes a range of
	      characters.
	    <programlisting>echo "abcdef"                 # abcdef
echo "abcdef" | tr -d b-d     # aef


tr -d 0-9 &lt;filename
# Deletes all digits from the file "filename".</programlisting></para>

            <para>The <option>--squeeze-repeats</option> (or
              <option>-s</option>) option deletes all but the
              first instance of a string of consecutive characters.
              This option is useful for removing excess <link
              linkend="whitespaceref">whitespace</link>.



	      <screen><prompt>bash$ </prompt><userinput>echo "XXXXX" | tr --squeeze-repeats 'X'</userinput>
<computeroutput>X</computeroutput></screen></para>

	    <para>The <option>-c</option> <quote>complement</quote>
	      option <emphasis>inverts</emphasis> the character set to
	      match. With this option, <command>tr</command> acts only
	      upon those characters <emphasis>not</emphasis> matching
	      the specified set.</para>

            <para>
	      <screen><prompt>bash$ </prompt><userinput>echo "acfdeb123" | tr -c b-d +</userinput>
<computeroutput>+c+d+b++++</computeroutput></screen>
            </para>



            <para>Note that <command>tr</command> recognizes <link
	      linkend="posixref">POSIX character classes</link>.
	         <footnote><para>This is only true of the GNU version of
		 <command>tr</command>, not the generic version often found on
		 commercial UNIX systems.</para></footnote>
	      </para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>echo "abcd2ef1" | tr '[:alpha:]' -</userinput>
<computeroutput>----2--1</computeroutput>
	      </screen>
	    </para>

	    <example id="ex49">
	      <title><command>toupper</command>: Transforms a file to all uppercase.</title>
	      <programlisting>&ex49;</programlisting>
	    </example>	    


	    <example id="lowercase">
	      <title><command>lowercase</command>: Changes all filenames in working directory to lowercase.</title>
	      <programlisting>&lowercase;</programlisting>
	    </example>	    

	    <example id="du">
	      <title><command>du</command>: DOS to UNIX text file conversion.</title>
	      <programlisting>&du;</programlisting>
	    </example>	    

	    <example id="rot13">
	      <title><command>rot13</command>: rot13, ultra-weak encryption.</title>
	      <programlisting>&rot13;</programlisting>
	    </example>	    

	    <example id="cryptoquote">
	      <title>Generating <quote>Crypto-Quote</quote> Puzzles</title>
	      <programlisting>&cryptoquote;</programlisting>
	    </example>


	    <sidebar><title><command>tr</command> variants</title>
	    <para>
	    The <command>tr</command> utility has two historic
	    variants. The BSD version does not use brackets
	    (<userinput>tr a-z A-Z</userinput>), but the SysV one does
	    (<userinput>tr '[a-z]' '[A-Z]'</userinput>). The GNU version
	    of <command>tr</command> resembles the BSD one, so quoting
	    letter ranges within brackets is mandatory.
	    </para>
	    </sidebar>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="foldref"><command>fold</command></term>
	  <indexterm>
	    <primary>fold</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>fold</secondary>
	  </indexterm>
	  <listitem>
	    <para>A filter that wraps lines of input to a specified width.
	      This is especially useful with the <option>-s</option>
	      option, which breaks lines at word spaces (see <xref
	      linkend="ex50"> and <xref linkend="mailformat">).</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>fmt</command></term>
	  <indexterm>
	    <primary>fmt</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>fmt</secondary>
	  </indexterm>
	  <listitem>
	    <para>Simple-minded file formatter, used as a filter in a
	      pipe to <quote>wrap</quote> long lines of text
	      output.</para>

	    <example id="ex50">
	      <title>Formatted file listing.</title>
	      <programlisting>&ex50;</programlisting>
	    </example>	    

	    <para>See also <xref linkend="ex41">.</para>

	    <tip><para>A powerful alternative to <command>fmt</command> is
	      Kamil Toman's <command>par</command>
	      utility, available from <ulink
	      url="http://www.cs.berkeley.edu/~amc/Par/">http://www.cs.berkeley.edu/~amc/Par/</ulink>.
	      </para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>col</command></term>
	  <indexterm>
	    <primary>col</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>reverse line feed</secondary>
	  </indexterm>
	  <listitem>
	    <para>This deceptively named filter removes reverse line feeds
	      from an input stream. It also attempts to replace
	      whitespace with equivalent tabs. The chief use of
	      <command>col</command> is in filtering the output
	      from certain text processing utilities, such as
	      <command>groff</command> and <command>tbl</command>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>column</command></term>
	  <indexterm>
	    <primary>column</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>column</secondary>
	  </indexterm>
	  <listitem>
	    <para>Column formatter. This filter transforms list-type
	      text output into a <quote>pretty-printed</quote> table
	      by inserting tabs at appropriate places.</para>

	    <example id="col">
	      <title>Using <command>column</command> to format a directory
	        listing</title>
	      <programlisting>&colm;</programlisting>
	    </example>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>colrm</command></term>
	  <indexterm>
	    <primary>colrm</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>colrm</secondary>
	  </indexterm>
	  <listitem>
	    <para>Column removal filter. This removes columns (characters)
	      from a file and writes the file, lacking the range of
	      specified columns, back to <filename>stdout</filename>.
	      <userinput>colrm 2 4 &lt;filename</userinput> removes the
	      second through fourth characters from each line of the
	      text file <filename>filename</filename>.</para>
	    <warning><para>If the file contains tabs or nonprintable
	      characters, this may cause unpredictable
	      behavior. In such cases, consider using
	      <link linkend="expandref">expand</link> and
	      <command>unexpand</command> in a pipe preceding
	      <command>colrm</command>.</para></warning>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>nl</command></term>
	  <indexterm>
	    <primary>nl</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>fmt</secondary>
	  </indexterm>
	  <listitem>
	    <para>Line numbering filter. <userinput>nl filename</userinput>
	    lists <filename>filename</filename> to
	    <filename>stdout</filename>, but inserts consecutive
	    numbers at the beginning of each non-blank line. If
	    <filename>filename</filename> omitted, operates on
	    <filename>stdin.</filename></para>

	    <para>The output of <command>nl</command> is very similar to
	      <userinput>cat -n</userinput>, however, by default
	      <command>nl</command> does not list blank lines.</para>

	    <example id="lnum">
	      <title><command>nl</command>: A self-numbering script.</title>
	      <programlisting>&lnum;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>pr</command></term>
	  <indexterm>
	    <primary>pr</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>pr</secondary>
	  </indexterm>
	  <listitem>
	    <para>Print formatting filter. This will paginate files
	      (or <filename>stdout</filename>) into sections suitable for
	      hard copy printing or viewing on screen.	Various options
	      permit row and column manipulation, joining lines, setting
	      margins, numbering lines, adding page headers, and merging
	      files, among other things. The <command>pr</command>
	      command combines much of the functionality of
	      <command>nl</command>, <command>paste</command>,
	      <command>fold</command>, <command>column</command>, and
	      <command>expand</command>.</para>

	   <para><userinput>pr -o 5 --width=65 fileZZZ | more</userinput>
	     gives a nice paginated listing to screen of
	     <filename>fileZZZ</filename> with margins set at 5 and
	     65.</para>

	    <para>A particularly useful option is <option>-d</option>,
	      forcing double-spacing (same effect as <command>sed
	      -G</command>).</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="gettextref"><command>gettext</command></term>
	  <indexterm>
	    <primary>gettext</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>localization</secondary>
	  </indexterm>
	  <listitem>

	    <para>The GNU <command>gettext</command> package is a set of
	      utilities for <link linkend="localization">localizing</link>
	      and translating the text output of programs into foreign
	      languages. While originally intended for C programs, it
	      now supports quite a number of programming and scripting
	      languages.</para>

	    <para>The  <command>gettext</command>
	      <emphasis>program</emphasis> works on shell scripts. See
	      the <replaceable>info page</replaceable>.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="msgfmtref"><command>msgfmt</command></term>
	  <indexterm>
	    <primary>msgfmt</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>localization</secondary>
	  </indexterm>
	  <listitem>
	    <para>A program for generating binary
	      message catalogs. It is used for <link
	      linkend="localization">localization</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>iconv</command></term>
	  <indexterm>
	    <primary>iconv</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>encoding</secondary>
	  </indexterm>
	  <listitem>
	    <para>A utility for converting file(s) to a different encoding
	      (character set). Its chief use is for <link
	      linkend="localization">localization</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>recode</command></term>
	  <indexterm>
	    <primary>recode</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>encoding</secondary>
	  </indexterm>
	  <listitem>
	    <para>Consider this a fancier version of
	      <command>iconv</command>, above. This very versatile utility
	      for converting a file to a different encoding is not part
	      of the standard Linux installation.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>TeX</command></term>
	  <term><command>gs</command></term>
	  <indexterm>
	    <primary>TeX</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>TeX</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>gs</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>Postscript</secondary>
	  </indexterm>
	  <listitem>

	    <para><command>TeX</command> and <command>Postscript</command>
	      are text markup languages used for preparing copy for
	      printing or formatted video display.</para>
		
	      <para><command>TeX</command> is Donald Knuth's elaborate
		typsetting system. It is often convenient to write a
		shell script encapsulating all the options and arguments
		passed to one of these markup languages.</para>

	      <para><emphasis>Ghostscript</emphasis>
		(<command>gs</command>) is a GPL-ed Postscript
		interpreter.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>groff</command></term>
	  <term><command>tbl</command></term>
	  <term><command>eqn</command></term>
	  <indexterm>
	    <primary>groff</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>groff</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>tbl</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>table</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>eqn</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>equation</secondary>
	  </indexterm>
	  <listitem>

            <para>Yet another text markup and display formatting language
	      is <command>groff</command>. This is the enhanced GNU version
	      of the venerable UNIX <command>roff/troff</command> display
	      and typesetting package. <emphasis>Manpages</emphasis>
	      use <command>groff</command> (see <xref linkend="manview">).</para>

	    <para>The <command>tbl</command> table processing utility
	      is considered part of <command>groff</command>, as its
	      function is to convert table markup into
	      <command>groff</command> commands.</para>

	    <para>The <command>eqn</command> equation processing utility
	      is likewise part of <command>groff</command>, and
	      its function is to convert equation markup into
	      <command>groff</command> commands.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>lex</command></term>
	  <term><command>yacc</command></term>
	  <indexterm>
	    <primary>lex</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>flex</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>yacc</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>bison</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>lex</command> lexical analyzer produces
	      programs for pattern matching. This has been replaced
	      by the nonproprietary <command>flex</command> on Linux
	      systems.</para>
	    <para>The <command>yacc</command> utility creates a
	      parser based on a set of specifications. This has been
	      replaced by the nonproprietary <command>bison</command>
	      on Linux systems.</para>
	  </listitem>
	</varlistentry>

       </variablelist>

        </sect1> <!-- End Text Processing Commands -->


      <sect1 id="filearchiv">
        <title>File and Archiving Commands</title>

       <variablelist id="faarchiving">
         <title><anchor id="faarchiving1">Archiving</title>

	<varlistentry>
	  <term><anchor id="tarref"><command>tar</command></term>
	  <indexterm>
	    <primary>tar</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tar</secondary>
	  </indexterm>
	  <listitem>

	    <para>The standard UNIX archiving utility. Originally a
	      <wordasword>Tape ARchiving</wordasword> program, it has
	      developed into a general purpose package that can handle
	      all manner of archiving with all types of destination
	      devices, ranging from tape drives to regular files to even
	      <filename>stdout</filename> (see <xref linkend="ex58">). GNU
	      tar has been patched to accept various compression
	      filters, such as <command>tar czvf archive_name.tar.gz
	      *</command>, which recursively archives and <link
	      linkend="gzipref">gzips</link> all files in a directory
	      tree except <link linkend="dotfilesref">dotfiles</link>
	      in the current working directory (<command>$PWD</command>).

		<footnote>
		  <para>
		    A <command>tar czvf archive_name.tar.gz *</command>
		    <emphasis>will</emphasis> include dotfiles in
		    directories <emphasis>below</emphasis> the current
		    working directory. This is an undocumented GNU
		    <command>tar</command> <quote>feature</quote>.
		  </para>
		</footnote>
            </para>		
		

	    <para>Some useful <command>tar</command> options:  
	      <orderedlist>

		<listitem><para><option>-c</option> create (a new
		  archive)</para></listitem>

		<listitem><para><option>-x</option> extract (files from
		  existing archive)</para></listitem>

		<listitem>
		<para><option>--delete</option> delete (files
		  from existing archive)</para>
		<caution><para>This option will not work on magnetic tape
		  devices.</para></caution>  
		  </listitem>

		<listitem><para><option>-r</option> append (files to
		  existing archive)</para></listitem>

		<listitem><para><option>-A</option> append
		  (<emphasis>tar</emphasis> files to
		  existing archive)</para></listitem>

		<listitem><para><option>-t</option> list (contents of
                  existing archive)</para></listitem>

	        <listitem><para><option>-u</option> update archive</para></listitem>

	        <listitem><para><option>-d</option> compare archive with
		  specified filesystem</para></listitem>

		<listitem>
		<para><option>-z</option> <link
		  linkend="gzipref">gzip</link> the archive</para>
		<para>(compress or uncompress, depending on whether
		combined with the <option>-c</option> or
		<option>-x</option>) option</para>
		</listitem>

		<listitem><para><option>-j</option>
		  <link linkend="bzipref">bzip2</link> the
		  archive</para></listitem>

	      </orderedlist>
	      </para>

	    <caution><para>It may be difficult to recover data from a
	      corrupted <emphasis>gzipped</emphasis> tar
	      archive. When archiving important files, make multiple
	      backups.</para></caution>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>shar</command></term>
	  <indexterm>
	    <primary>shar</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>archive</secondary>
	  </indexterm>
	  <listitem>

	    <para>Shell archiving utility. The files in a shell archive
	      are concatenated without compression, and the resultant
	      archive is essentially a shell script, complete with
	      <token>#!/bin/sh</token> header, and containing all
	      the necessary unarchiving commands.  Shar archives
	      still show up in Internet newsgroups, but otherwise
	      <command>shar</command> has been pretty well replaced by
	      <command>tar</command>/<command>gzip</command>. The
	      <command>unshar</command> command unpacks
	      <command>shar</command> archives.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>ar</command></term>
	  <indexterm>
	    <primary>ar</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>archive</secondary>
	  </indexterm>
	  <listitem>
	    <para>Creation and manipulation utility for archives, mainly
	      used for binary object file libraries.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="rpmref"><command>rpm</command></term>
	  <indexterm>
	    <primary>rpm</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>package manager</secondary>
	  </indexterm>
	  <listitem>

	    <para>The <emphasis>Red Hat Package Manager</emphasis>, or
	      <command>rpm</command> utility provides a wrapper for
	      source or binary archives. It includes commands for
	      installing and checking the integrity of packages, among
	      other things.</para>

	    <para>A simple <command>rpm -i package_name.rpm</command>
	      usually suffices to install a package, though there are many
	      more options available.</para>

	    <tip>
	    <para>An <userinput>rpm -qa</userinput> gives a
	      complete list of all installed <emphasis>rpm</emphasis> packages
	      on a given system. An <userinput>rpm -qa package_name</userinput>
	      lists only the package(s) corresponding to
	      <filename>package_name</filename>.</para>

	  <para>
	      <screen>
<prompt>bash$ </prompt><userinput>rpm -qa</userinput>
<computeroutput>redhat-logos-1.1.3-1
 glibc-2.2.4-13
 cracklib-2.7-12
 dosfstools-2.7-1
 gdbm-1.8.0-10
 ksymoops-2.4.1-1
 mktemp-1.5-11
 perl-5.6.0-17
 reiserfs-utils-3.x.0j-2
 ...</computeroutput>


<prompt>bash$ </prompt><userinput>rpm -qa docbook-utils</userinput>
<computeroutput>docbook-utils-0.6.9-2</computeroutput>


<prompt>bash$ </prompt><userinput>rpm -qa docbook | grep docbook</userinput>
<computeroutput>docbook-dtd31-sgml-1.0-10
 docbook-style-dsssl-1.64-3
 docbook-dtd30-sgml-1.0-10
 docbook-dtd40-sgml-1.0-11
 docbook-utils-pdf-0.6.9-2
 docbook-dtd41-sgml-1.0-10
 docbook-utils-0.6.9-2</computeroutput>
	      </screen>
	    </para>
	    </tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>cpio</command></term>
	  <indexterm>
	    <primary>cpio</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cpio</secondary>
	  </indexterm>
	  <listitem>
	    <para>This specialized archiving copy command
	      (<command>c</command>o<command>p</command>y
	      <command>i</command>nput and <command>o</command>utput)
	      is rarely seen any more, having been supplanted by
	      <command>tar</command>/<command>gzip</command>. It still
	      has its uses, such as moving a directory tree.</para>

	    <example id="ex48">
	      <title>Using <command>cpio</command> to move a directory tree</title>
	      <programlisting>&ex48;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>rpm2cpio</command></term>
	  <indexterm>
	    <primary>rpm</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cpio</secondary>
	  </indexterm>
	  <listitem>
	    <para>This command extracts a
	      <command>cpio</command> archive from an <link
	      linkend="rpmref">rpm</link> one.</para>

	    <example id="derpm">
	      <title>Unpacking an <emphasis>rpm</emphasis> archive</title>
	      <programlisting>&derpm;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="facompression">
        <title><anchor id="facompression1">Compression</title>

	<varlistentry>
	  <term><anchor id="gzipref"><command>gzip</command></term>
	  <indexterm>
	    <primary>gzip</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>gzip</secondary>
	  </indexterm>
	  <listitem>

	    <para>The standard GNU/UNIX compression utility, replacing
	      the inferior and proprietary
	      <command>compress</command>. The corresponding decompression
	      command is <command>gunzip</command>, which is the equivalent of
	      <command>gzip -d</command>.</para>

	    <para>The <command>zcat</command> filter decompresses a
	      <emphasis>gzipped</emphasis> file to
	      <filename>stdout</filename>, as possible input to a pipe or
	      redirection. This is, in effect, a <command>cat</command>
	      command that works on compressed files (including files
	      processed with the older <command>compress</command>
	      utility). The <command>zcat</command> command is equivalent to
	      <command>gzip -dc</command>.</para>

	    <caution><para>On some commercial UNIX systems, <command>zcat</command>
	      is a synonym for <command>uncompress -c</command>,
	      and will not work on <emphasis>gzipped</emphasis>
	      files.</para></caution>

	      <para>See also <xref linkend="ex14">.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="bzipref"><command>bzip2</command></term>
	  <indexterm>
	    <primary>bzip2</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>bzip2</secondary>
	  </indexterm>
	  <listitem>

	    <para>An alternate compression utility, usually more efficient
	      (but slower) than <command>gzip</command>, especially on
	      large files. The corresponding decompression command is
	      <command>bunzip2</command>.</para>

	    <note><para>Newer versions of <link
	      linkend="tarref">tar</link> have been patched with
	      <command>bzip2</command> support.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>compress</command></term>
	  <term><command>uncompress</command></term>
	  <indexterm>
	    <primary>compress</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>compress</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>uncompress</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uncompress</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is an older, proprietary compression
	      utility found in commercial UNIX distributions. The
	      more efficient <command>gzip</command> has largely
	      replaced it. Linux distributions generally include a
	      <command>compress</command> workalike for compatibility,
	      although <command>gunzip</command> can unarchive files
	      treated with <command>compress</command>.</para>

	    <tip><para>The <command>znew</command> command transforms
	      <emphasis>compressed</emphasis> files into
	      <emphasis>gzipped</emphasis> ones.</para></tip>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sq</command></term>
	  <indexterm>
	    <primary>sq</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sq</secondary>
	  </indexterm>
	  <listitem>

	    <para>Yet another compression utility, a filter that works
	      only on sorted ASCII word lists. It uses the standard
	      invocation syntax for a filter, <command>sq < input-file >
	      output-file</command>.  Fast, but not nearly as efficient
	      as <link linkend="gzipref">gzip</link>.  The corresponding
	      uncompression filter is <command>unsq</command>, invoked
	      like <command>sq</command>.</para>

	      <tip><para>The output of <command>sq</command> may be
	        piped to <command>gzip</command> for further
		compression.</para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>zip</command></term>
	  <term><command>unzip</command></term>
	  <indexterm>
	    <primary>zip</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>pkzip.exe</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>unzip</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>unzip</secondary>
	  </indexterm>
	  <listitem>
	    <para>Cross-platform file archiving and compression utility
	      compatible with DOS <emphasis>pkzip.exe</emphasis>.
	      <quote>Zipped</quote> archives seem to be a more
	      acceptable medium of exchange on the Internet than
	      <quote>tarballs</quote>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>unarc</command></term>
	  <term><command>unarj</command></term>
	  <term><command>unrar</command></term>
	  <indexterm>
	    <primary>unarc</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>arc.exe</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>unarj</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>arj.exe</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>unrar</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>rar.exe</secondary>
	  </indexterm>
	  <listitem>
	    <para>These Linux utilities permit unpacking archives
	      compressed with the DOS <emphasis>arc.exe</emphasis>,
	      <emphasis>arj.exe</emphasis>, and
	      <emphasis>rar.exe</emphasis> programs.</para>

	  </listitem>
	</varlistentry>



      </variablelist>


      <variablelist id="fainformation">
        <title><anchor id="fainformation1">File Information</title>

	<varlistentry>
	  <term><anchor id="fileref"><command>file</command></term>
	  <indexterm>
	    <primary>file</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>file</secondary>
	  </indexterm>
	  <listitem>

	    <para>A utility for identifying file types. The command
	      <userinput>file file-name</userinput> will return a
	      file specification for <filename>file-name</filename>,
	      such as <computeroutput>ascii text</computeroutput> or
	      <computeroutput>data</computeroutput>. It references
	      the <link linkend="magnumref">magic numbers</link>
	      found in <filename>/usr/share/magic</filename>,
	      <filename>/etc/magic</filename>, or
	      <filename>/usr/lib/magic</filename>, depending on the
	      Linux/UNIX distribution.</para>

	    <para>The <option>-f</option> option causes
	      <command>file</command> to run in batch mode, to read from
	      a designated file a list of filenames to analyze. The
	      <option>-z</option> option, when used on a compressed
	      target file, forces an attempt to analyze the uncompressed
	      file type.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>file test.tar.gz</userinput>
<computeroutput>test.tar.gz: gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix</computeroutput>

<prompt>bash </prompt><userinput>file -z test.tar.gz</userinput>
<computeroutput>test.tar.gz: GNU tar archive (gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix)</computeroutput>
	      </screen>
	    </para>

	    <example id="stripc">
	      <title>Stripping comments from C program files</title>
	      <programlisting>&stripc;</programlisting>
	    </example>	    	   

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="whichref"><command>which</command></term>
	  <indexterm>
	    <primary>which</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>which</secondary>
	  </indexterm>
	  <listitem>
	    <para><command>which command-xxx</command> gives the full path
	      to <quote>command-xxx</quote>. This is useful for finding
	      out whether a particular command or utility is installed
	      on the system.</para>
	    <para><userinput>$bash which rm</userinput>
<screen><computeroutput>/usr/bin/rm</computeroutput></screen>
	  </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>whereis</command></term>
	  <indexterm>
	    <primary>whereis</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>whereis</secondary>
	  </indexterm>
	  <listitem>
	    <para>Similar to <command>which</command>, above,
	      <command>whereis command-xxx</command> gives the
	      full path to <quote>command-xxx</quote>, but also to its
	      <emphasis>manpage</emphasis>.</para>
	    <para><userinput>$bash whereis rm</userinput>
<screen><computeroutput>rm: /bin/rm /usr/share/man/man1/rm.1.bz2</computeroutput></screen>
	  </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="whatisref"><command>whatis</command></term>
	  <indexterm>
	    <primary>whatis</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>whatis</secondary>
	  </indexterm>
	  <listitem>
	    <para><command>whatis filexxx</command> looks up
	      <quote>filexxx</quote> in the
	      <replaceable>whatis</replaceable> database. This is useful
	      for identifying system commands and important configuration
	      files. Consider it a simplified <command>man</command>
	      command.</para>
	    <para><userinput>$bash whatis whatis</userinput>
<screen><computeroutput>whatis               (1)  - search the whatis database for complete words</computeroutput></screen>
	  </para>
	  
      <example id="what">
	<title><command>Exploring <filename
	class="directory">/usr/X11R6/bin</filename></command></title>
	<programlisting>&what;</programlisting>
      </example>

            <para>See also <xref linkend="fileinfo">.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>vdir</command></term>
	  <indexterm>
	    <primary>vdir</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>ls</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show a detailed directory listing. The effect is similar to
	      <link linkend="lsref">ls -l</link>.</para>
	    <para>This is one of the GNU <emphasis>fileutils</emphasis>.</para>  
	      <para>
	      <screen><prompt>bash$ </prompt><userinput>vdir</userinput>
<computeroutput>total 10
 -rw-r--r--    1 bozo  bozo      4034 Jul 18 22:04 data1.xrolo
 -rw-r--r--    1 bozo  bozo      4602 May 25 13:58 data1.xrolo.bak
 -rw-r--r--    1 bozo  bozo       877 Dec 17  2000 employment.xrolo</computeroutput>

<prompt>bash </prompt><userinput>ls -l</userinput>
<computeroutput>total 10
 -rw-r--r--    1 bozo  bozo      4034 Jul 18 22:04 data1.xrolo
 -rw-r--r--    1 bozo  bozo      4602 May 25 13:58 data1.xrolo.bak
 -rw-r--r--    1 bozo  bozo       877 Dec 17  2000 employment.xrolo</computeroutput>
	      </screen>
	      </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>locate</command></term>
	  <term><command>slocate</command></term>
	  <indexterm>
	    <primary>locate</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>locate</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>slocate</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>slocate</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>locate</command> command searches for files using a
	      database stored for just that purpose. The
	      <command>slocate</command> command is the secure version of
	      <command>locate</command> (which may be aliased to
	      <command>slocate</command>).</para>
	    <para><userinput>$bash locate hickson</userinput>
<screen><computeroutput>/usr/lib/xephem/catalogs/hickson.edb</computeroutput></screen></para>
	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>readlink</command></term>
	  <indexterm>
	    <primary>readlink</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>link</secondary>
	  </indexterm>
	  <listitem>
	    <para>Disclose the file that a symbolic link points to.</para>
	    <para>
	      <screen><prompt>bash$ </prompt><userinput>readlink /usr/bin/awk</userinput>
<computeroutput>../../bin/gawk</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>strings</command></term>
	  <indexterm>
	    <primary>strings</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>strings</secondary>
	  </indexterm>
	  <listitem>
	    <para>Use the <command>strings</command> command to find
	      printable strings in a binary or data file. It will list
	      sequences of printable characters found in the target
	      file. This might be handy for a quick 'n dirty examination
	      of a core dump or for looking at an unknown graphic image
	      file (<userinput>strings image-file | more</userinput> might
	      show something like <computeroutput>JFIF</computeroutput>,
	      which would identify the file as a <emphasis>jpeg</emphasis>
	      graphic). In a script, you would probably
	      parse the output of <command>strings</command>
	      with <link linkend="grepref">grep</link> or <link
	      linkend="sedref">sed</link>. See <xref linkend="bingrep">
	      and <xref linkend="findstring">.</para>

	    <example id="wstrings">
	      <title>An <quote>improved</quote> <emphasis>strings</emphasis>
	        command</title>
	      <programlisting>&wstrings;</programlisting>
	    </example>
	  </listitem>

	</varlistentry>

      </variablelist>

      <variablelist id="comparisonn">
        <title><anchor id="comparisonn1">Comparison</title>

	<varlistentry>
	  <term><anchor id="diffref"><command>diff</command></term>
	  <term><command>patch</command></term>
	  <indexterm>
	    <primary>diff</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>diff</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>patch</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>patch</secondary>
	  </indexterm>
	  <listitem>
	    <para><command>diff</command>: flexible file comparison
	      utility. It compares the target files line-by-line
	      sequentially.  In some applications, such as comparing
	      word dictionaries, it may be helpful to filter the
	      files through <link linkend="sortref">sort</link>
	      and <command>uniq</command> before piping them
	      to <command>diff</command>. <userinput>diff file-1
	      file-2</userinput> outputs the lines in the files that
	      differ, with carets showing which file each particular
	      line belongs to.</para>

	  <para>The <option>--side-by-side</option> option to
	    <command>diff</command> outputs each compared file, line by
	    line, in separate columns, with non-matching lines marked. The
	    <option>-c</option> and <option>-u</option> options likewise
	    make the output of the command easier to interpret.</para>

          <para>There are available various fancy frontends for
	    <command>diff</command>, such as <command>spiff</command>,
	    <command>wdiff</command>, <command>xdiff</command>, and
	    <command>mgdiff</command>. </para>

	  <tip><para>The <command>diff</command> command returns an exit
	    status of 0 if the compared files are identical, and 1 if
	    they differ. This permits use of <command>diff</command>
	    in a test construct within a shell script (see
	    below).</para></tip>


	    <para>A common use for <command>diff</command> is generating
	      difference files to be used with <command>patch</command>
	      The <option>-e</option> option outputs files suitable
	      for <command>ed</command> or <command>ex</command>
	      scripts.</para>


	    <para><command>patch</command>: flexible versioning
	      utility. Given a difference file generated by
	      <command>diff</command>, <command>patch</command> can
	      upgrade a previous version of a package to a newer version.
	      It is much more convenient to distribute a relatively
	      small <quote>diff</quote> file than the entire body of a
	      newly revised package. Kernel <quote>patches</quote> have
	      become the preferred method of distributing the frequent
	      releases of the Linux kernel.</para>

	    <para><programlisting>patch -p1 &lt;patch-file
# Takes all the changes listed in 'patch-file'
# and applies them to the files referenced therein.
# This upgrades to a newer version of the package.</programlisting></para>

	    <para>Patching the kernel:</para>
            <para><programlisting>cd /usr/src
gzip -cd patchXX.gz | patch -p0
# Upgrading kernel source using 'patch'.
# From the Linux kernel docs "README",
# by anonymous author (Alan Cox?).</programlisting></para>

            <note>
	    <para>The <command>diff</command> command can also
	      recursively compare directories (for the filenames
	      present).</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>diff -r ~/notes1 ~/notes2</userinput>
<computeroutput>Only in /home/bozo/notes1: file02
 Only in /home/bozo/notes1: file03
 Only in /home/bozo/notes2: file04</computeroutput>
	      </screen>
	    </para>
            </note>

	    <tip><para>Use <command>zdiff</command> to compare
	      <emphasis>gzipped</emphasis> files.</para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>diff3</command></term>
	  <indexterm>
	    <primary>diff3</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>diff3</secondary>
	  </indexterm>
	  <listitem>
	    <para>An extended version of <command>diff</command> that compares
	      three files at a time. This command returns an exit value
	      of 0 upon successful execution, but unfortunately this gives
	      no information about the results of the comparison.</para>
	      <para>
	      <screen><prompt>bash$ </prompt><userinput>diff3 file-1 file-2 file-3</userinput>
<computeroutput>====
 1:1c
   This is line 1 of "file-1".
 2:1c
   This is line 1 of "file-2".
 3:1c
   This is line 1 of "file-3"</computeroutput>
	      </screen>
	      </para>
	      
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sdiff</command></term>
	  <indexterm>
	    <primary>sdiff</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sdiff</secondary>
	  </indexterm>
	  <listitem>
	    <para>Compare and/or edit two files in order to merge
	      them into an output file. Because of its interactive nature,
	      this command would find little use in a script.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>cmp</command></term>
	  <indexterm>
	    <primary>cmp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cmp</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>cmp</command> command is a simpler version of
	      <command>diff</command>, above. Whereas <command>diff</command>
	      reports the differences between two files,
	      <command>cmp</command> merely shows at what point they
	      differ.</para>

	  <note><para>Like <command>diff</command>, <command>cmp</command>
	    returns an exit status of 0 if the compared files are
	    identical, and 1 if they differ. This permits use in a test
	    construct within a shell script.</para></note>

	    <example id="filecomp">
	      <title>Using <command>cmp</command> to compare two files
	        within a script.</title>
	      <programlisting>&filecomp;</programlisting>
	    </example>	    	   

	    <tip><para>Use <command>zcmp</command> on
	      <emphasis>gzipped</emphasis> files.</para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>comm</command></term>
	  <indexterm>
	    <primary>comm</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>comm</secondary>
	  </indexterm>
	  <listitem>
	    <para>Versatile file comparison utility. The files must be
	      sorted for this to be useful.</para>

	    <para><command>comm
		<replaceable>-options</replaceable>
		<replaceable>first-file</replaceable>
		<replaceable>second-file</replaceable></command></para>

	    <para><userinput>comm file-1 file-2</userinput> outputs three columns:
	      <itemizedlist>
		<listitem><para>column 1 = lines unique to <filename>file-1</filename></para>
		</listitem>
		
		<listitem><para>column 2 = lines unique to <filename>file-2</filename></para>
		</listitem>
		
		<listitem><para>column 3 = lines common to both.</para>
		</listitem>
	      </itemizedlist></para>
	      
	    <para>The options allow suppressing output of one or more columns.
	      <itemizedlist>
		<listitem><para><option>-1</option> suppresses column
		    <literal>1</literal></para>
		</listitem>
		<listitem><para><option>-2</option> suppresses column
		    <literal>2</literal></para>
		</listitem>
		<listitem><para><option>-3</option> suppresses column
		    <literal>3</literal></para>
		</listitem>
		<listitem><para><option>-12</option> suppresses both columns
		    <literal>1</literal> and <literal>2</literal>, etc.</para>
		</listitem>
		</itemizedlist>
	    </para>
	      
	  </listitem>
	</varlistentry>


      </variablelist>

      <variablelist id="fautils">
        <title><anchor id="fautils1">Utilities</title>

	<varlistentry>
	  <term><command>basename</command></term>
	  <indexterm>
	    <primary>basename</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>basename</secondary>
	  </indexterm>
	  <listitem><para>Strips the path information from a file name, printing
	      only the file name. The construction  <userinput>basename
		$0</userinput> lets the script know its name, that is, the name it
	      was invoked by. This can be used for <quote>usage</quote> messages if, 
	      for example a script is called with missing arguments:
              <programlisting>echo "Usage: `basename $0` arg1 arg2 ... argn"</programlisting>
	    </para>

	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term><command>dirname</command></term>
	  <indexterm>
	    <primary>dirname</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>dirname</secondary>
	  </indexterm>
	  <listitem><para>Strips the <command>basename</command> from
	    a filename, printing only the path information.</para>
	    <note>
	      <para><command>basename</command> and <command>dirname</command>
		can operate on any arbitrary string. The argument
		does not need to refer to an existing file, or
		even be a filename for that matter (see <xref
		linkend="daysbetween">).</para>
	    </note>
	    
	    <example id="ex35">
	      <title><command>basename</command> and <command>dirname</command></title>
	      <programlisting>&ex35;</programlisting>
	    </example>	    
	    
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>split</command></term>
	  <indexterm>
	    <primary>split</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>split</secondary>
	  </indexterm>
	  <listitem>
	    <para>Utility for splitting a file into smaller chunks. Usually used 
	      for splitting up large files in order to back them up on floppies or
	      preparatory to e-mailing or uploading them.</para>
	      
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sum</command></term>
	  <term><command>cksum</command></term>
	  <term><anchor id="md5sumref"><command>md5sum</command></term>
	  <indexterm>
	    <primary>sum</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sum</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>cksum</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cksum</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>md5sum</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>md5sum</secondary>
	  </indexterm>
	  <listitem>
	    <para>These are utilities for generating checksums. A
	      <emphasis>checksum</emphasis> is a number mathematically
	      calculated from the contents of a file, for the purpose
	      of checking its integrity. A script might refer to a list
	      of checksums for security purposes, such as ensuring that
	      the contents of key system files have not been altered
	      or corrupted. For security applications, use the 128-bit
	      <command>md5sum</command> (<command>m</command>essage
	      <command>d</command>igest check<command>sum</command>)
	      command.</para>


	  <para>
	      <screen>
<prompt>bash$ </prompt><userinput>cksum /boot/vmlinuz</userinput>
<computeroutput>1670054224 804083 /boot/vmlinuz</computeroutput>


<prompt>bash$ </prompt><userinput>md5sum /boot/vmlinuz</userinput>
<computeroutput>0f43eccea8f09e0a0b2b5cf1dcf333ba  /boot/vmlinuz</computeroutput>
	      </screen>
	  </para>


	  <para>Note that <command>cksum</command> also shows the size,
	    in bytes, of the target file.</para>

	    <example id="fileintegrity">
	      <title>Checking file integrity</title>
	      <programlisting>&fileintegrity;</programlisting>
	    </example>

	  <para>See also <xref linkend="directoryinfo"> for a creative use of
	    the <command>md5sum</command> command.</para> 

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="shredref"><command>shred</command></term>
	  <indexterm>
	    <primary>shred</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>secure delete</secondary>
	  </indexterm>
	  <listitem>

	    <para>Securely erase a file by overwriting it multiple times with
	      random bit patterns before deleting it. This command has
	      the same effect as <xref linkend="blotout">, but does it
	      in a more thorough and elegant manner.</para>

	    <para>This is one of the GNU <emphasis>fileutils</emphasis>.</para>  

	    <caution><para>Advanced forensic technology may still be able to
	      recover the contents of a file, even after application of
	      <command>shred</command>.</para></caution>
	    
	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="faencencr">
        <title><anchor id="faencencr1">Encoding and Encryption</title>

	<varlistentry>
	  <term><command>uuencode</command></term>
	  <indexterm>
	    <primary>uuencode</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uuencode</secondary>
	  </indexterm>
	  <listitem>
	    <para>This utility encodes binary files into ASCII characters, making them
	      suitable for transmission in the body of an e-mail message or in a
	      newsgroup posting.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>uudecode</command></term>
	  <indexterm>
	    <primary>uudecode</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uudecode</secondary>
	  </indexterm>
	  <listitem>
	    <para>This reverses the encoding, decoding uuencoded files back into the
	      original binaries.</para>

	    <example id="ex52">
	      <title>Uudecoding encoded files</title>
	      <programlisting>&ex52;</programlisting>
	    </example>	    	   

	  <tip><para>The <link linkend="foldref">fold -s</link> command
	    may be useful (possibly in a pipe) to process long uudecoded
	    text messages downloaded from Usenet newsgroups.</para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>mimencode</command></term>
	  <term><command>mmencode</command></term>
	  <indexterm>
	    <primary>mimencode</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>mime</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>mmencode</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>encode</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>mimencode</command> and
	      <command>mmencode</command> commands process
	      multimedia-encoded e-mail attachments. Although
	      <emphasis>mail user agents</emphasis> (such as
	      <command>pine</command> or <command>kmail</command>)
	      normally handle this automatically, these particular
	      utilities permit manipulating such attachments manually
	      from the command line or in a batch by means of a shell
	      script.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>crypt</command></term>
	  <indexterm>
	    <primary>crypt</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>crypt</secondary>
	  </indexterm>
	  <listitem>
	    <para>At one time, this was the standard UNIX file encryption
	      utility.

              <footnote><para>This is a symmetric block cipher, used to
	        encrypt files on a single system or local network, as opposed
		to the <quote>public key</quote> cipher class, of which
		<command>pgp</command> is a well-known
		example.</para></footnote>

	      Politically motivated government regulations
	      prohibiting the export of encryption software resulted
	      in the disappearance of <command>crypt</command>
	      from much of the UNIX world, and it is still
	      missing from most Linux distributions. Fortunately,
	      programmers have come up with a number of decent
	      alternatives to it, among them the author's very own <ulink
	      url="ftp://metalab.unc.edu/pub/Linux/utils/file/cruft-0.2.tar.gz">cruft</ulink>
	      (see <xref linkend="encryptedpw">).  </para>

	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="famisc">
        <title><anchor id="famisc1">Miscellaneous</title>

	<varlistentry>
	  <term><anchor id="mktempref"><command>mktemp</command></term>
	  <indexterm>
	    <primary>temporary</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>filename</secondary>
	  </indexterm>
	  <listitem>
	    <para>Create a temporary file with a <quote>unique</quote>
	    filename.</para>
	    <para><programlisting>PREFIX=filename
tempfile=`mktemp $PREFIX.XXXXXX`
#                        ^^^^^^ Need at least 6 placeholders
#+                              in the filename template.
echo "tempfile name = $tempfile"
# tempfile name = filename.QA2ZpY
#                 or something similar...</programlisting></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>make</command></term>
	  <indexterm>
	    <primary>make</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>Makefile</secondary>
	  </indexterm>
	  <listitem>
	    <para>Utility for building and compiling binary packages. 
	      This can also be used for any set of operations that is
	      triggered by incremental changes in source files.</para>
	    <para><anchor id="makefileref"></para>
	    <para>The <command>make</command> command checks a
	    <filename>Makefile</filename>, a list of file dependencies and
	      operations to be carried out.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>install</command></term>
	  <indexterm>
	    <primary>install</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>install</secondary>
	  </indexterm>
	  <listitem>
	    <para>Special purpose file copying command, similar to
	      <command>cp</command>, but capable of setting permissions
	      and attributes of the copied files. This command seems
	      tailormade for installing software packages, and as such it
	      shows up frequently in <filename>Makefiles</filename>
	      (in the <replaceable>make install :</replaceable>
	      section). It could likewise find use in installation
	      scripts.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>dos2unix</command></term>
	  <indexterm>
	    <primary>dos2unix</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>file converter</secondary>
	  </indexterm>
	  <listitem>
	    <para>This utility, written by Benjamin Lin and collaborators,
	      converts DOS-formatted text files (lines terminated by
	      CR-LF) to UNIX format (lines terminated by LF only),
	      and vice-versa.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>ptx</command></term>
	  <indexterm>
	    <primary>ptx</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>index</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>ptx [targetfile]</command> command
	      outputs a permuted index (cross-reference list) of the
	      targetfile. This may be further filtered and formatted in a
	      pipe, if necessary.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>more</command></term>
	  <term><command>less</command></term>
	  <indexterm>
	    <primary>more</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>more</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>less</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>less</secondary>
	  </indexterm>
	  <listitem>
	    <para>Pagers that display a text file or stream to
	      <filename>stdout</filename>, one screenful at a time.
	      These may be used to filter the output of a script.</para>
	  </listitem>
	</varlistentry>
       
       </variablelist>	

	</sect1> <!-- End File and Archiving Commands -->



      <sect1 id="communications">
        <title>Communications Commands</title>
	<para>Certain of the following commands find use in <link
	  linkend="cspammers">chasing spammers</link>, as well as in
	  network data transfer and analysis.</para>

       <variablelist id="communinfo">
         <title><anchor id="communinfo1">Information and Statistics</title>

	<varlistentry>
	  <term><command>host</command></term>
	  <indexterm>
	    <primary>host</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>host</secondary>
	  </indexterm>
	  <listitem>
	    <para>Searches for information about an Internet host by name or
	      IP address, using DNS.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>host surfacemail.com</userinput>
<computeroutput>surfacemail.com. has address 202.92.42.236</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>ipcalc</command></term>
	  <indexterm>
	    <primary>ipcalc</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>ipcalc</secondary>
	  </indexterm>
	  <listitem>
	    <para>Carries out IP address lookups.
	      With the <option>-h</option> option,
	      <command>ipcalc</command> does a reverse DNS lookup, finding
	      the name of the host (server) from the IP address.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>ipcalc -h 202.92.42.236</userinput>
<computeroutput>HOSTNAME=surfacemail.com</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>nslookup</command></term>
	  <indexterm>
	    <primary>nslookup</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>name server lookup</secondary>
	  </indexterm>
	  <listitem>

	    <para>Do an Internet <quote>name server lookup</quote>
	      on a host by IP address. This is essentially equivalent
	      to <command>ipcalc -h</command> or <command>dig -x
	      </command>. The command may be run either interactively
	      or noninteractively, i.e., from within a script.</para>

	    <para>The <command>nslookup</command> command has allegedly
	      been <quote>deprecated,</quote> but it still has its
	      uses.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>nslookup -sil 66.97.104.180</userinput>
<computeroutput>nslookup kuhleersparnis.ch
 Server:         135.116.137.2
 Address:        135.116.137.2#53

 Non-authoritative answer:
 Name:   kuhleersparnis.ch</computeroutput>
	      </screen>
	  </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>dig</command></term>
	  <indexterm>
	    <primary>dig</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>domain information groper</secondary>
	  </indexterm>
	  <listitem>

	    <para>Similar to <command>nslookup</command>, do an Internet
	      <quote>name server lookup</quote> on a host.  May be run
	      either interactively or noninteractively, i.e., from within
	      a script.</para>

	    <para>Compare the output of <command>dig -x</command> with
	      <command>ipcalc -h</command> and
	      <command>nslookup</command>.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>dig -x 81.9.6.2</userinput>
<computeroutput>;; Got answer:
 ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 11649
 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

 ;; QUESTION SECTION:
 ;2.6.9.81.in-addr.arpa.         IN      PTR

 ;; AUTHORITY SECTION:
 6.9.81.in-addr.arpa.    3600    IN      SOA     ns.eltel.net. noc.eltel.net.
 2002031705 900 600 86400 3600

 ;; Query time: 537 msec
 ;; SERVER: 135.116.137.2#53(135.116.137.2)
 ;; WHEN: Wed Jun 26 08:35:24 2002
 ;; MSG SIZE  rcvd: 91</computeroutput>
	      </screen>
	  </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>traceroute</command></term>
	  <indexterm>
	    <primary>traceroute</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>traceroute</secondary>
	  </indexterm>
	  <listitem>

	    <para>Trace the route taken by packets sent to a remote host. This
	      command works within a LAN, WAN, or over the
	      Internet. The remote host may be specified by an IP
	      address. The output of this command may be filtered
	      by <link linkend="grepref">grep</link> or <link
	      linkend="sedref">sed</link> in a pipe.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>traceroute 81.9.6.2</userinput>
<computeroutput>traceroute to 81.9.6.2 (81.9.6.2), 30 hops max, 38 byte packets
 1  tc43.xjbnnbrb.com (136.30.178.8)  191.303 ms  179.400 ms  179.767 ms
 2  or0.xjbnnbrb.com (136.30.178.1)  179.536 ms  179.534 ms  169.685 ms
 3  192.168.11.101 (192.168.11.101)  189.471 ms  189.556 ms *
 ...</computeroutput>
	      </screen>
	  </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>ping</command></term>
	  <indexterm>
	    <primary>ping</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>ping</secondary>
	  </indexterm>
	  <listitem>

	    <para>Broadcast an <quote>ICMP ECHO_REQUEST</quote> packet to
	      other machines, either on a local or remote network. This
	      is a diagnostic tool for testing network connections,
	      and it should be used with caution.</para>

	    <para>A successful <command>ping</command> returns an <link
	      linkend="exitstatusref">exit status</link> of
	      <errorcode>0</errorcode>. This can be tested for in a
	      script.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>ping localhost</userinput>
<computeroutput>PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
 Warning: time of day goes back, taking countermeasures.
 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=709 usec
 64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=286 usec

 --- localhost.localdomain ping statistics ---
 2 packets transmitted, 2 packets received, 0% packet loss
 round-trip min/avg/max/mdev = 0.286/0.497/0.709/0.212 ms</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="whoisref"><command>whois</command></term>
	  <indexterm>
	    <primary>whois</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>domain name server</secondary>
	  </indexterm>
	  <listitem>
	    <para>Perform a DNS (Domain Name System) lookup.
	      The <option>-h</option> option permits specifying which
	      <emphasis>whois</emphasis> server to query. See <xref
	      linkend="ex18">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>finger</command></term>
	  <indexterm>
	    <primary>finger</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>finger</secondary>
	  </indexterm>
	  <listitem>

	    <para>Retrieve information about users on a
	      network. Optionally, this command can display
	      a user's <filename>~/.plan</filename>,
	      <filename>~/.project</filename>, and
	      <filename>~/.forward</filename> files, if present.</para>

	  <para>
	      <screen>
<prompt>bash$ </prompt><userinput>finger</userinput>
<computeroutput>Login  Name           Tty      Idle  Login Time   Office     Office Phone
 bozo   Bozo Bozeman   tty1        8  Jun 25 16:59
 bozo   Bozo Bozeman   ttyp0          Jun 25 16:59
 bozo   Bozo Bozeman   ttyp1          Jun 25 17:07</computeroutput>



<prompt>bash$ </prompt><userinput>finger bozo</userinput>
<computeroutput>Login: bozo                             Name: Bozo Bozeman
 Directory: /home/bozo                   Shell: /bin/bash
 On since Fri Aug 31 20:13 (MST) on tty1    1 hour 38 minutes idle
 On since Fri Aug 31 20:13 (MST) on pts/0   12 seconds idle
 On since Fri Aug 31 20:13 (MST) on pts/1
 On since Fri Aug 31 20:31 (MST) on pts/2   1 hour 16 minutes idle
 No mail.
 No Plan.</computeroutput>
	      </screen>
	    </para>
	      
	    <para>Out of security considerations, many networks disable
	      <command>finger</command> and its associated daemon.
	          <footnote>
		  <para><anchor id="daemonref"></para>
		  <para>A <emphasis>daemon</emphasis> is a background
		    process not attached to a terminal session. Daemons
		    perform designated services either at specified times
		    or explicitly triggered by certain events.</para>
		  <para>The word <quote>daemon</quote> means ghost in
		    Greek, and there is certainly something mysterious,
		    almost supernatural, about the way UNIX daemons
		    silently wander about behind the scenes, carrying
		    out their appointed tasks.</para>
	          </footnote>
	      </para>
	  
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>vrfy</command></term>
	  <indexterm>
	    <primary>vrfy</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>vrfy</secondary>
	  </indexterm>
	  <listitem>
	    <para>Verify an Internet e-mail address.</para>
	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="commremote">
        <title><anchor id="commremote1">Remote Host Access</title>

	<varlistentry>
	  <term><command>sx</command></term>
	  <term><command>rx</command></term>
	  <indexterm>
	    <primary>sx</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sx</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>rx</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>rx</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>sx</command> and <command>rx</command>
	      command set serves to transfer files to and from a remote
	      host using the <emphasis>xmodem</emphasis> protocol. These
	      are generally part of a communications package, such as
	      <command>minicom</command>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sz</command></term>
	  <term><command>rz</command></term>
	  <indexterm>
	    <primary>sz</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sz</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>rz</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>rz</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>sz</command> and <command>rz</command>
	      command set serves to transfer files to and from a remote
	      host using the <emphasis>zmodem</emphasis> protocol.
	      <emphasis>Zmodem</emphasis> has certain advantages over
	      <emphasis>xmodem</emphasis>, such as faster transmission
	      rate and resumption of interrupted file transfers.
	      Like <command>sx</command> and <command>rx</command>,
	      these are generally part of a communications package.</para>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="ftpref"><command>ftp</command></term>
	  <indexterm>
	    <primary>ftp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>file transfer</secondary>
	  </indexterm>
	  <listitem>
	    <para>Utility and protocol for uploading / downloading
	      files to or from a remote host. An ftp session can be automated
	      in a script (see <xref linkend="ex72">, <xref
	      linkend="encryptedpw">, and <xref linkend="ftpget">).</para>
	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>uucp</command></term>
	  <indexterm>
	    <primary>uucp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uucp</secondary>
	  </indexterm>
	  <listitem>

	    <para><emphasis>UNIX to UNIX copy</emphasis>. This is a
	      communications package for transferring files between UNIX
	      servers. A shell script is an effective way to handle a
	      <command>uucp</command> command sequence.</para>

	    <para>Since the advent of the Internet and e-mail,
	      <command>uucp</command> seems to have faded into obscurity,
	      but it still exists and remains perfectly workable in
	      situations where an Internet connection is not available
	      or appropriate.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>cu</command></term>
	  <indexterm>
	    <primary>cu</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>call up</secondary>
	  </indexterm>
	  <listitem>
	    <para><emphasis>C</emphasis>all <emphasis>U</emphasis>p
	      a remote system and connect as a simple terminal. This
	      command is part of the <command>uucp</command> package. It
	      is a sort of dumbed-down version of <link
	      linkend="telnetref">telnet</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="telnetref"><command>telnet</command></term>
	  <indexterm>
	    <primary>telnet</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>telnet</secondary>
	  </indexterm>
	  <listitem>
	    <para>Utility and protocol for connecting to a remote host.</para>
	    <caution><para>The telnet protocol contains security holes and
	      should therefore probably be avoided.</para></caution>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>wget</command></term>
	  <indexterm>
	    <primary>wget</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>download</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>wget</command> utility
	      <emphasis>non-interactively</emphasis> retrieves or
	      downloads files from a Web or ftp site. It works well in a
	      script.
	        <programlisting>wget -p http://www.xyz23.com/file01.html
wget -r ftp://ftp.xyz24.net/~bozo/project_files/ -o $SAVEFILE</programlisting>
            </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>lynx</command></term>
	  <indexterm>
	    <primary>lynx</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>browser</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>lynx</command> Web and file browser
	      can be used inside a script (with the
	      <option>-dump</option> option) to retrieve a file from a Web or 
	      ftp site non-interactively.
	        <programlisting>lynx -dump http://www.xyz23.com/file01.html &gt;$SAVEFILE</programlisting>
            </para>		
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>rlogin</command></term>
	  <indexterm>
	    <primary>rlogin</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>remote login</secondary>
	  </indexterm>
	  <listitem>
	    <para><replaceable>Remote login</replaceable>, initates a
	      session on a remote host. This command has security issues,
	      so use <link linkend="sshref">ssh</link> instead.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>rsh</command></term>
	  <indexterm>
	    <primary>rsh</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>remote shell</secondary>
	  </indexterm>
	  <listitem>
	    <para><replaceable>Remote shell</replaceable>, executes
	      command(s) on a remote host. This has security issues,
	      so use <command>ssh</command> instead.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>rcp</command></term>
	  <indexterm>
	    <primary>rcp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>remote copy</secondary>
	  </indexterm>
	  <listitem>
	    <para><replaceable>Remote copy</replaceable>, copies files
	      between two different networked machines.  Using
	      <command>rcp</command> and similar utilities with
	      security implications in a shell script may not be
	      advisable. Consider, instead, using <command>ssh</command>
	      or an <command>expect</command> script.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="sshref"><command>ssh</command></term>
	  <indexterm>
	    <primary>ssh</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>secure shell</secondary>
	  </indexterm>
	  <listitem>
	    <para><replaceable>Secure shell</replaceable>, logs onto
	      a remote host and executes commands there. This
	      secure replacement for <command>telnet</command>,
	      <command>rlogin</command>, <command>rcp</command>, and
	      <command>rsh</command> uses identity authentication
	      and encryption. See its <emphasis>manpage</emphasis>
	      for details.</para>
	  </listitem>
	</varlistentry>
       
       </variablelist>	


      <variablelist id="commlocal">
        <title><anchor id="commlocal1">Local Network</title>

	<varlistentry>
	  <term><anchor id="writeref"><command>write</command></term>
	  <indexterm>
	    <primary>write</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>write</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is a utility for terminal-to-terminal communication.
	      It allows sending lines from your terminal (console
	      or xterm) to that of another user. The <link
	      linkend="mesgref">mesg</link> command may, of course,
	      be used to disable write access to a terminal</para>

	    <para>Since <command>write</command> is interactive, it
	      would not normally find use in a script.</para>
	  </listitem>
	</varlistentry>

       </variablelist>	


      <variablelist id="commmail">
        <title><anchor id="commmail1">Mail</title>

	<varlistentry>
	  <term><command>mail</command></term>
	  <indexterm>
	    <primary>mail</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>mail</secondary>
	  </indexterm>
	  <listitem>

	    <para>Send or read e-mail messages.</para>

            <para>This stripped-down command-line mail client
	      works fine as a command embedded in a script.</para>

	    <example id="selfmailer">
	      <title>A script that mails itself</title>
	      <programlisting>&selfmailer;</programlisting>
	    </example>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>mailto</command></term>
	  <indexterm>
	    <primary>mailto</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>MIME mail</secondary>
	  </indexterm>
	  <listitem>
	    <para>Similar to the <command>mail</command> command,
	      <command>mailto</command> sends e-mail messages
	      from the command line or in a script. However,
	      <command>mailto</command> also permits sending MIME
	      (multimedia) messages.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>vacation</command></term>
	  <indexterm>
	    <primary>vacation</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>mail</secondary>
	  </indexterm>
	  <listitem>
	    <para>This utility automatically replies to e-mails that
	      the intended recipient is on vacation and temporarily
	      unavailable. This runs on a network, in conjunction with
	      <command>sendmail</command>, and is not applicable to a
	      dial-up POPmail account.</para>
	  </listitem>
	</varlistentry>


       </variablelist>	

	</sect1> <!-- End Communications Commands -->



      <sect1 id="terminalccmds">
        <title>Terminal Control Commands</title>

       <variablelist id="termcommandlisting">	
         <title><anchor id="termcommandlisting1">Command affecting the console
	   or terminal</title>

	<varlistentry>
	  <term><command>tput</command></term>
	  <indexterm>
	    <primary>tput</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>terminal</secondary>
	  </indexterm>
	  <listitem>

	    <para>Initialize terminal and/or fetch information about it from
	      <filename>terminfo</filename> data. Various options permit
	      certain terminal operations.  <command>tput clear</command>
	      is the equivalent of <command>clear</command>,
	      below. <command>tput reset</command> is the equivalent
	      of <command>reset</command>, below. <command>tput
	      sgr0</command> also resets the terminal, but without
	      clearing the screen.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>tput longname</userinput>
<computeroutput>xterm terminal emulator (XFree86 4.0 Window System)</computeroutput>
	      </screen>
	    </para>

	    <para>Issuing a <command>tput cup X Y</command> moves
	      the cursor to the (X,Y) coordinates in the current
	      terminal. A <command>clear</command> to erase the terminal
	      screen would normally precede this.</para>

	    <para>Note that <link linkend="sttyref">stty</link> offers
	      a more powerful command set for controlling a terminal.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>infocmp</command></term>
	  <indexterm>
	    <primary>infocmp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>terminal</secondary>
	  </indexterm>
	  <listitem>

	    <para>This command prints out extensive information about the
	      current terminal. It references the
	      <emphasis>terminfo</emphasis> database.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>infocmp</userinput>
<computeroutput>#       Reconstructed via infocmp from file:
 /usr/share/terminfo/r/rxvt
 rxvt|rxvt terminal emulator (X Window System), 
         am, bce, eo, km, mir, msgr, xenl, xon, 
         colors#8, cols#80, it#8, lines#24, pairs#64, 
         acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, 
         bel=^G, blink=\E[5m, bold=\E[1m,
         civis=\E[?25l, 
         clear=\E[H\E[2J, cnorm=\E[?25h, cr=^M, 
         ...</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>reset</command></term>
	  <indexterm>
	    <primary>reset</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>reset</secondary>
	  </indexterm>
	  <listitem>
	    <para>Reset terminal parameters and clear text screen. As with
	    <command>clear</command>, the cursor and prompt reappear in the
	    upper lefthand corner of the terminal.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="clearref"><command>clear</command></term>
	  <indexterm>
	    <primary>clear</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>clear</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>clear</command> command simply clears
	      the text screen at the console or in an xterm. The
	      prompt and cursor reappear at the upper lefthand corner
	      of the screen or xterm window. This command may be used
	      either at the command line or in a script. See <xref
	      linkend="ex30">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>script</command></term>
	  <indexterm>
	    <primary>script</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>script</secondary>
	  </indexterm>
	  <listitem>
	    <para>This utility records (saves to a file) all the user keystrokes at
	      the command line in a console or an xterm window. This, in effect,
	      creates a record of a session.</para>
	  </listitem>
	</varlistentry>

       </variablelist>	

	</sect1> <!-- End Terminal Control Commands -->

	
      <sect1 id="mathc">
        <title>Math Commands</title>

       <variablelist id="mathcommandlisting">	
         <title><anchor id="mathcommandlisting1"><quote>Doing the
	   numbers</quote></title>

      <varlistentry>
	<term><command>factor</command></term>
	  <indexterm>
	    <primary>factor</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>factor</secondary>
	  </indexterm>
	  <listitem><para>Decompose an integer into prime factors.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>factor 27417</userinput>
<computeroutput>27417: 3 13 19 37</computeroutput>
	      </screen>
	    </para>

	    </listitem>
	  </varlistentry>

	<varlistentry>
	  <term><anchor id="bcref"><command>bc</command></term>
	  <indexterm>
	    <primary>bc</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>bc</secondary>
	  </indexterm>
	  <listitem>

	    <para>Bash can't handle floating point calculations, and
	      it lacks operators for certain important mathematical
	      functions. Fortunately, <command>bc</command> comes to
	      the rescue.</para>

	    <para>Not just a versatile, arbitrary precision calculation
	      utility, <command>bc</command> offers many of the facilities of
	      a programming language.</para>

	    <para><command>bc</command> has a syntax vaguely resembling C.</para>

	    <para>Since it is a fairly well-behaved UNIX utility, and may
	       therefore be used in a <link linkend="piperef">pipe</link>,
	       <command>bc</command> comes in handy in scripts.</para>

	    <para>Here is a simple template for using
	      <command>bc</command> to calculate a script
	      variable. This uses <link linkend="commandsubref">command
	      substitution</link>.</para>

	      <para>
              <screen>
	      <userinput>variable=$(echo "OPTIONS; OPERATIONS" | bc)</userinput>
	      </screen>
	      </para>

            <example id="monthlypmt">
              <title>Monthly Payment on a Mortgage</title>
              <programlisting>&monthlypmt;</programlisting>
            </example>

            <example id="base">
              <title>Base Conversion</title>
              <programlisting>&base;</programlisting>
            </example>

	      <para>An alternate method of invoking <command>bc</command>
		involves using a <link linkend="heredocref">here
		document</link> embedded within a <link
		linkend="commandsubref">command substitution</link>
		block. This is especially appropriate when a script
		needs to pass a list of options and commands to
		<command>bc</command>.</para>

              <para>
	      <programlisting>variable=`bc << LIMIT_STRING
options
statements
operations
LIMIT_STRING
`

...or...


variable=$(bc << LIMIT_STRING
options
statements
operations
LIMIT_STRING
)</programlisting>
              </para>


            <example id="altbc">
              <title>Invoking <command>bc</command> using a <quote>here
	        document</quote></title>
              <programlisting>&altbc;</programlisting>
            </example>

            <example id="cannon">
              <title>Calculating PI</title>
              <programlisting>&cannon;</programlisting>
            </example>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="dcref"><command>dc</command></term>
	  <indexterm>
	    <primary>dc</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>dc</secondary>
	  </indexterm>
	  <listitem>

	    <para>The <command>dc</command> (<command>d</command>esk
	    <command>c</command>alculator) utility is stack-oriented
	      and uses RPN (<quote>Reverse Polish Notation</quote>). Like
	      <command>bc</command>, it has much of the power of a
	      programming language.</para>

              <para>Most persons avoid <command>dc</command>, since it
	        requires non-intuitive RPN input. Yet it has its uses.</para>

            <example id="hexconvert">
              <title>Converting a decimal number to hexadecimal</title>
              <programlisting>&hexconvert;</programlisting>
            </example>

	      <para>Studying the <emphasis>info</emphasis> page for
		<command>dc</command> gives some insight into its
		intricacies. However, there seems to be a small,
		select group of <emphasis>dc wizards</emphasis> who
		delight in showing off their mastery of this powerful,
		but arcane utility.</para>

            <example id="factr">
              <title>Factoring</title>
              <programlisting>&factr;</programlisting>
            </example>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="awkmath"><command>awk</command></term>
	  <indexterm>
	    <primary>awk</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>math</secondary>
	  </indexterm>
	  <listitem>
	    <para>Yet another way of doing floating point math in
	      a script is using <link linkend="awkref">awk's</link>
	      built-in math functions in a <link linkend="shwrapper">shell
	      wrapper</link>.</para>

            <example id="hypot">
              <title>Calculating the hypotenuse of a triangle</title>
              <programlisting>&hypot;</programlisting>
            </example>

	  </listitem>
	</varlistentry>

       </variablelist>	

	</sect1> <!-- End Math Commands -->


      <sect1 id="extmisc">
        <title>Miscellaneous Commands</title>

       <variablelist id="misccommandlisting">	
         <title><anchor id="misccommandlisting1">Command that fit in no
	   special category</title>

	<varlistentry>
	  <term><command>jot</command></term>
	  <term><command>seq</command></term>
	  <indexterm>
	    <primary>jot</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>jot</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>seq</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>seq</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>loop</primary>
	    <secondary>arguments</secondary>
	  </indexterm>
	  <listitem>
	    <para>These utilities emit a sequence of integers, with a
	      user-selected increment.</para>

	    <para>The normal separator character between each integer is a
	      newline, but this can be changed with the <option>-s</option>
	      option.</para>
	    <para>
	      <screen>
<prompt>bash$ </prompt><userinput>seq 5</userinput>
<computeroutput>1
 2
 3
 4
 5</computeroutput>



<prompt>bash$ </prompt><userinput>seq -s : 5</userinput>
<computeroutput>1:2:3:4:5</computeroutput>
	      </screen>
	    </para>
	      
	      
	    <para>Both <command>jot</command> and <command>seq</command>
	      come in handy in a <link linkend="forloopref1">for
	      loop</link>.</para>

	    <example id="ex53">
	      <title>Using <command>seq</command> to generate loop arguments</title>
	      <programlisting>&ex53;</programlisting>
	    </example>	    	   
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="getopty"><command>getopt</command></term>
	  <indexterm>
	    <primary>getopt</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>option</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>getopt</command> command
	      parses command-line options preceded by a <link
	      linkend="dashref">dash</link>. This external command
	      corresponds to the <link linkend="getoptsx">getopts</link>
	      Bash builtin, but it is not nearly as versatile.</para>

	    <example id="ex33a">
	      <title>Using <command>getopt</command> to parse command-line
	        options</title>
	      <programlisting>&ex33a;</programlisting>
	    </example>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="runpartsref"><command>run-parts</command></term>
	  <indexterm>
	    <primary>run-parts</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>run-parts</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>run-parts</command> command

		<footnote><para>This is actually a script adapted from
		the Debian Linux distribution.</para></footnote>
	      
	      executes all the scripts in a target directory, sequentially
	      in ASCII-sorted filename order. Of course, the scripts
	      need to have execute permission.</para>
	      
	    <para>The <link linkend="cronref">crond</link> <link
	      linkend="daemonref">daemon</link> invokes
	      <command>run-parts</command> to run the scripts in
	      the <filename class="directory">/etc/cron.*</filename>
	      directories.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>yes</command></term>
	  <indexterm>
	    <primary>yes</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>yes</secondary>
	  </indexterm>
	  <listitem>

	    <para>In its default behavior the <command>yes</command>
	      command feeds a continuous string of the character
	      <computeroutput>y</computeroutput> followed
	      by a line feed to <filename>stdout</filename>. A
	      <keycombo><keycap>control</keycap><keycap>c</keycap></keycombo>
	      terminates the run. A different output string
	      may be specified, as in <userinput>yes different
	      string</userinput>, which would continually output
	      <computeroutput>different string</computeroutput> to
	      <filename>stdout</filename>.  One might well ask the purpose
	      of this. From the command line or in a script, the output
	      of <command>yes</command> can be redirected or piped into a
	      program expecting user input. In effect, this becomes a sort
	      of poor man's version of <command>expect</command>.</para>

	    <para><userinput>yes | fsck /dev/hda1</userinput> runs
	      <command>fsck</command> non-interactively (careful!).</para>

	   <para><userinput>yes | rm -r dirname</userinput> has same effect as
	     <userinput>rm -rf dirname</userinput> (careful!).</para>

	   <warning><para>Caution advised when piping <command>yes</command>
	     to a potentially dangerous system command, such
	     as <link linkend="fsckref">fsck</link> or <link
	     linkend="fdiskref">fdisk</link>. It may have unintended
	     side-effects.</para></warning>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>banner</command></term>
	  <indexterm>
	    <primary>banner</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>banner</secondary>
	  </indexterm>
	  <listitem>
	    <para>Prints arguments as a large vertical banner to
	      <filename>stdout</filename>, using an ASCII character
	      (default '#'). This may be redirected to a printer for
	      hardcopy.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>printenv</command></term>
	  <indexterm>
	    <primary>printenv</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>environment</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show all the <link linkend="envref">environmental
	      variables</link> set for a particular user.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>printenv | grep HOME</userinput>
<computeroutput>HOME=/home/bozo</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>lp</command></term>
	  <indexterm>
	    <primary>lp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>lpr</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>lp</command> and <command>lpr</command>
	      commands send file(s) to the print queue, to be printed as
	      hard copy.

	      <footnote><para>The <emphasis>print queue</emphasis> is
	      the group of jobs <quote>waiting in line</quote> to be
	      printed.</para></footnote>

	      These commands trace the origin of their names to the
	      line printers of another era.</para>

	      <para><prompt>bash$ </prompt><userinput>lp file1.txt</userinput>
	        or <prompt>bash </prompt><userinput>lp
		&lt;file1.txt</userinput></para>

	      <para>It is often useful to pipe the formatted output from
	        <command>pr</command> to <command>lp</command>.</para>

	      <para><prompt>bash$ </prompt><userinput>pr -options file1.txt | lp</userinput>
	        </para>

	      <para>Formatting packages, such as <command>groff</command> and
	        <emphasis>Ghostscript</emphasis> may send their output
		directly to <command>lp</command>.</para>

	      <para><prompt>bash$ </prompt><userinput>groff -Tascii file.tr | lp</userinput>
	        </para>

	      <para><prompt>bash$ </prompt><userinput>gs -options | lp file.ps</userinput>
	        </para>

	      <para>Related commands are <command>lpq</command>, for viewing
	        the print queue, and <command>lprm</command>, for removing
		jobs from the print queue.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>tee</command></term>
	  <indexterm>
	    <primary>tee</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tee</secondary>
	  </indexterm>
	  <listitem>
	    <para>[UNIX borrows an idea here from the plumbing trade.]</para>
	    <para>This is a redirection operator, but with a difference. Like the
	      plumber's <quote>tee,</quote> it permits <quote>siponing
              off</quote> <emphasis>to a file </emphasis>the output of a command 
	      or commands within a pipe, but without affecting the result. This is
	      useful for printing an ongoing process to a file or paper, perhaps to
	      keep track of it for debugging purposes.</para>
	    
	    <screen>
                   tee
                 |------> to file
                 |
  ===============|===============
  command--->----|-operator-->---> result of command(s)
  ===============================
	      </screen>


	    <para><programlisting>cat listfile* | sort | tee check.file | uniq > result.file</programlisting>
	      (The file <filename>check.file</filename> contains
	      the concatenated sorted <quote>listfiles</quote>,
	      before the duplicate lines are removed by <link
	      linkend="uniqref">uniq</link>.)</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>mkfifo</command></term>
	  <indexterm>
	    <primary>mkfifo</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>mkfifo</secondary>
	  </indexterm>
	  <listitem>
	    <para><anchor id="namedpiperef">This obscure command
	      creates a <emphasis>named pipe</emphasis>, a temporary
	      <emphasis>first-in-first-out buffer</emphasis> for
	      transferring data between processes.

		<footnote><para>For an excellent overview of this
		  topic, see Andy Vaught's article, <ulink
		  url="http://www2.linuxjournal.com/lj-issues/issue41/2156.html">Introduction
		  to Named Pipes</ulink>, in the September, 1997 issue
		  of <ulink url="http://www.linuxjournal.com">Linux
		  Journal</ulink>.</para></footnote>

	      Typically, one process writes to the FIFO, and the other
	      reads from it. See <xref linkend="fifo">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>pathchk</command></term>
	  <indexterm>
	    <primary>pathchk</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>pathchk</secondary>
	  </indexterm>
	  <listitem>
	    <para>This command checks the validity of a filename. If the
	      filename exceeds the maximum allowable length (255
	      characters) or one or more of the directories in
	      its path is not searchable, then an error message
	      results.</para>
	      
	    <para>Unfortunately, <command>pathchk</command> does
	      not return a recognizable error code, and it is therefore
	      pretty much useless in a script. Consider instead the
	      <link linkend="rtif">file test operators</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="ddref"><command>dd</command></term>
	  <indexterm>
	    <primary>dd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>dd</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is the somewhat obscure and much feared <quote>data
	      duplicator</quote> command.  Originally a utility
	      for exchanging data on magnetic tapes between UNIX
	      minicomputers and IBM mainframes, this command still
	      has its uses.  The <command>dd</command> command simply
	      copies a file (or <filename>stdin/stdout</filename>), but
	      with conversions. Possible conversions are ASCII/EBCDIC,
	        
		<footnote><para>EBCDIC (pronounced
		  <quote>ebb-sid-ic</quote>) is an acronym for Extended
		  Binary Coded Decimal Interchange Code. This is an IBM
		  data format no longer in much use. A bizarre
		  application of the <option>conv=ebcdic</option> option
		  of <command>dd</command> is as a quick 'n easy, but
		  not very secure text file encoder.
		    <programlisting>cat $file | dd conv=swab,ebcdic > $file_encrypted
# Encode (looks like gibberish).		    
# Might as well switch bytes (swab), too, for a little extra obscurity.

cat $file_encrypted | dd conv=swab,ascii > $file_plaintext
# Decode.</programlisting>
                </para></footnote>

	      upper/lower case, swapping of byte pairs between input
	      and output, and skipping and/or truncating the head or
	      tail of the input file. A <userinput>dd --help</userinput>
	      lists the conversion and other options that this powerful
	      utility takes.</para>

	    <para><programlisting># Exercising 'dd'.

n=3
p=5
input_file=project.txt
output_file=log.txt

dd if=$input_file of=$output_file bs=1 skip=$((n-1)) count=$((p-n+1)) 2> /dev/null
# Extracts characters n to p from file $input_file.




echo -n "hello world" | dd cbs=1 conv=unblock 2> /dev/null
# Echoes "hello world" vertically.


# Thanks, S.C.</programlisting></para>


	    <para>To demonstrate just how versatile <command>dd</command> is,
	     let's use it to capture keystrokes.</para>

	    <example id="ddkeypress">
	      <title>Capturing Keystrokes</title>
	      <programlisting>&ddkeypress;</programlisting>
	    </example>	    

	    <para>The <command>dd</command> command can do random access on a
	      data stream.

	        <programlisting>echo -n . | dd bs=1 seek=4 of=file conv=notrunc
# The "conv=notrunc" option means that the output file will not be truncated.		

# Thanks, S.C.</programlisting>
            </para>


	    <para>The <command>dd</command> command can copy raw data
	      and disk images to and from devices, such as floppies and
	      tape drives (<xref linkend="copycd">). A common use is
	      creating boot floppies.</para>
             <para>
		<userinput>dd if=kernel-image of=/dev/fd0H1440</userinput>
             </para>

             <para>Similarly, <command>dd</command> can copy the entire
	       contents of a floppy, even one formatted with a
	       <quote>foreign</quote> OS, to the hard drive as an
	       image file.</para>
             <para>
		<userinput>dd if=/dev/fd0 of=/home/bozo/projects/floppy.img</userinput>
             </para>

             <para>
	      Other applications of <command>dd</command> include
	      initializing temporary swap files (<xref linkend="ex73">)
	      and ramdisks (<xref linkend="ramdisk">). It can even do a
	      low-level copy of an entire hard drive partition, although
	      this is not necessarily recommended.</para>

	    <para>People (with presumably nothing better to do with
	      their time) are constantly thinking of interesting
	      applications of <command>dd</command>.</para>

	    <example id="blotout">
	      <title>Securely deleting a file</title>
	      <programlisting>&blotout;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="odref"><command>od</command></term>
	  <indexterm>
	    <primary>od</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>od</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>od</command>, or <emphasis>octal
	      dump</emphasis> filter converts input (or files) to octal
	      (base-8) or other bases. This is useful for viewing or
	      processing binary data files or otherwise unreadable system
	      device files, such as <filename>/dev/urandom</filename>,
	      and as a filter for binary data. See <xref
	      linkend="seedingrandom"> and <xref linkend="rnd">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>hexdump</command></term>
	  <indexterm>
	    <primary>hexdump</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>hexadecimal</secondary>
	  </indexterm>
	  <listitem>
	    <para>Performs a hexadecimal, octal, decimal, or ASCII
	      dump of a binary file. This command is the rough equivalent
	      of <command>od</command>, above, but not nearly as
	      useful.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>objdump</command></term>
	  <indexterm>
	    <primary>objdump</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>object binary dump</secondary>
	  </indexterm>
	  <listitem>
	    <para>Displays an object file or binary executable in either
	      hexadecimal form or as a disassembled listing (with the
	      <option>-d</option> option).</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>objdump -d /bin/ls</userinput>
<computeroutput>/bin/ls:     file format elf32-i386

 Disassembly of section .init:

 080490bc &lt;.init&gt;:
  80490bc:       55                      push   %ebp
  80490bd:       89 e5                   mov    %esp,%ebp
  . . .</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>mcookie</command></term>
	  <indexterm>
	    <primary>magic</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>cookie</secondary>
	  </indexterm>
	  <listitem>
	    <para>This command generates a <quote>magic cookie</quote>, a
	    128-bit (32-character) pseudorandom hexadecimal number,
	    normally used as an authorization <quote>signature</quote>
	    by the X server. This also available for use in a script as
	    a <quote>quick 'n dirty</quote> random number.
	      <programlisting>random000=`mcookie | sed -e '2p'`
# Uses 'sed' to strip off extraneous characters.</programlisting>
	    </para>

	    <para>Of course, a script could use <link
	    linkend="md5sumref">md5</link> for the same purpose.
	      <programlisting># Generate md5 checksum on the script itself.
random001=`md5sum $0 | awk '{print $1}'`
# Uses 'awk' to strip off the filename.</programlisting>
	    </para>

	    <para>The <command>mcookie</command> command gives yet another way
	      to generate a <quote>unique</quote> filename.</para>

	    <example id="tempfilename">
	      <title>Filename generator</title>
	      <programlisting>&tempfilename;</programlisting>
	    </example>
	      
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>units</command></term>
	  <indexterm>
	    <primary>units</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>conversion</secondary>
	  </indexterm>
	  <listitem>
	    <para>This utility converts between different units of measure.
	      While normally invoked in interactive mode,
	      <command>units</command> may find use in a script.</para>
	    <example id="unitconversion">
	      <title>Converting meters to miles</title>
	      <programlisting>&unitconversion;</programlisting>
	    </example>
	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>m4</command></term>
	  <indexterm>
	    <primary>m4</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>macro</secondary>
	  </indexterm>
	  <listitem>
	    <para>A hidden treasure, <command>m4</command> is a
	      powerful macro processing filter,
		 <footnote><para>A <emphasis>macro</emphasis> is a
		 symbolic constant that expands into a command string
		 or a set of operations on parameters.</para></footnote>
	      virtually a complete language. Although
	      originally written as a pre-processor for
	      <emphasis>RatFor</emphasis>, <command>m4</command>
	      turned out to be useful as a stand-alone utility. In
	      fact, <command>m4</command> combines some of the
	      functionality of <link linkend="evalref">eval</link>,
	      <link linkend="trref">tr</link>, and <link
	      linkend="awkref">awk</link>, in addition to its extensive
	      macro expansion facilities.</para>

	    <para>The April, 2002 issue of <ulink
	      url="http://www.linuxjournal.com">Linux
	      Journal</ulink> has a very nice article on
	      <command>m4</command> and its uses.</para>

	    <example id="m4">
	      <title>Using m4</title>
	      <programlisting>&m4;</programlisting>
	    </example>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>doexec</command></term>
	  <indexterm>
	    <primary>doexec</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>executable arg list</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>doexec</command> command enables passing
	      an arbitrary list of arguments to a <emphasis>binary
	      executable</emphasis>. In particular, passing
	      <varname>argv[0]</varname> (which corresponds to <link
	      linkend="posparamref1">$0</link> in a script) lets the
	      executable be invoked by various names, and it can then
	      carry out different sets of actions, according to the name
	      by which it was called. What this amounts to is roundabout
	      way of passing options to an executable.</para>

	    <para>For example, the <filename
	      class="directory">/usr/local/bin</filename> directory might
	      contain a binary called <quote>aaa</quote>.  Invoking
	      <command>doexec /usr/local/bin/aaa list</command>
	      would <emphasis>list</emphasis> all those files
	      in the current working directory beginning with an
	      <quote>a</quote>, while invoking (the same executable
	      with) <command>doexec /usr/local/bin/aaa delete </command>
	      would <emphasis>delete</emphasis> those files.</para>

            <note><para>The various behaviors of the executable
              must be defined within the code of the executable itself,
              analogous to something like the following in a shell script:
                <programlisting>case `basename $0` in
"name1" ) do_something;;
"name2" ) do_something_else;;
"name3" ) do_yet_another_thing;;
*       ) bail_out;;
esac</programlisting></para></note>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><command>dialog</command></term>
	  <indexterm>
	    <primary>dialog</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>dialog</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <link linkend="dialogref">dialog</link> family of tools
	      provide a method of calling interactive
	      <quote>dialog</quote> boxes from a script. The more
	      elaborate variations of <command>dialog</command> --
	      <command>gdialog</command>, <command>Xdialog</command>,
	      and <command>kdialog</command> -- actually invoke X-Windows
	      widgets. See <xref linkend="dialog">.</para>
	  </listitem>
	</varlistentry>


      </variablelist>

        </sect1> <!-- End Miscellaneous Commands -->

  </chapter> <!-- External Filters, Programs and Commands -->



  <chapter id="system">
    <title>System and Administrative Commands</title>


      <para>The startup and shutdown scripts in 
	<filename class="directory">/etc/rc.d</filename> illustrate the uses
	(and usefulness) of many of these comands. These are usually
	invoked by root and used for system maintenance or emergency
	filesystem repairs. Use with caution, as some of these commands
	may damage your system if misused.</para>

      <variablelist id="usersgroups">
        <title><anchor id="usersgroups1">Users and Groups</title>

	<varlistentry>
	  <term><command>users</command></term>
	  <indexterm>
	    <primary>users</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>users</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show all logged on users. This is the approximate
	      equivalent of <command>who -q</command>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>groups</command></term>
	  <indexterm>
	    <primary>groups</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>groups</secondary>
	  </indexterm>
	  <listitem>
	    <para>Lists the current user and the groups she belongs to.
	       This corresponds to the <link
	       linkend="groupsref">$GROUPS</link> internal variable,
	       but gives the group names, rather than the numbers.</para>
	    <screen><prompt>bash$ </prompt><userinput>groups</userinput>
<computeroutput>bozita cdrom cdwriter audio xgrp</computeroutput>

<prompt>bash$ </prompt><userinput>echo $GROUPS</userinput>
<computeroutput>501</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>chown</command></term>
	  <term><command>chgrp</command></term>
	  <indexterm>
	    <primary>chown</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>chown</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>chgrp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>chgrp</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>chown</command> command changes the
	      ownership of a file or files. This command is a useful
	      method that <replaceable>root</replaceable> can use to
	      shift file ownership from one user to another. An ordinary
	      user may not change the ownership of files, not even her
	      own files.
	         <footnote><para>This is the case on a Linux machine or a UNIX
		   system with disk quotas.</para></footnote>
	      </para>

	  <para>
	      <screen><prompt>root# </prompt><userinput>chown bozo *.txt</userinput>
<computeroutput></computeroutput>
	      </screen>
	    </para>

	    <para>The <command>chgrp</command> command changes the
	      <replaceable>group</replaceable> ownership of a file or
	      files. You must be owner of the file(s) as well as a member
	      of the destination group (or <replaceable>root</replaceable>)
	      to use this operation.
	      <programlisting>chgrp --recursive dunderheads *.data
#  The "dunderheads" group will now own all the "*.data" files
#+ all the way down the $PWD directory tree (that's what "recursive" means).
</programlisting></para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>useradd</command></term>
	  <term><command>userdel</command></term>
	  <indexterm>
	    <primary>useradd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>useradd</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>userdel</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>userdel</secondary>
	  </indexterm>
	  <listitem>
	    <para>The <command>useradd</command> administrative command
	      adds a user account to the system and creates a home
	      directory for that particular user, if so specified. The
	      corresponding <command>userdel</command> command removes
	      a user account from the system
		 <footnote><para>The <command>userdel</command> command
		   will fail if the particular user being deleted is
		   still logged on.</para></footnote>
	      and deletes associated files.</para>

	    <note><para>The <command>adduser</command> command is a synonym
	      for <command>useradd</command> and is usually a symbolic link to
	      it.</para></note>

	  </listitem>
	</varlistentry>


	<varlistentry>
	  <term><anchor id="idref"><command>id</command></term>
	  <indexterm>
	    <primary>id</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>id</secondary>
	  </indexterm>
	  <listitem>

	    <para>The <command>id</command> command lists the real and
	      effective user IDs and the group IDs of
	      the current user.  This is the counterpart
	      to the <link linkend="uidref">$UID</link>,
	      <link linkend="euidref">$EUID</link>, and <link
	      linkend="groupsref">$GROUPS</link> internal Bash
	      variables.</para>

	    <screen><prompt>bash$ </prompt><userinput>id</userinput>
<computeroutput>uid=501(bozo) gid=501(bozo) groups=501(bozo),22(cdrom),80(cdwriter),81(audio)</computeroutput>

<prompt>bash$ </prompt><userinput>echo $UID</userinput>
<computeroutput>501</computeroutput></screen>

            <para>Also see <xref linkend="amiroot">.</para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="whoref"><command>who</command></term>
	  <indexterm>
	    <primary>who</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>whoami</secondary>
	  </indexterm>
	  <listitem>

	    <para>Show all users logged on to the system.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>who</userinput>
<computeroutput>bozo  tty1     Apr 27 17:45
 bozo  pts/0    Apr 27 17:46
 bozo  pts/1    Apr 27 17:47
 bozo  pts/2    Apr 27 17:49
</computeroutput>
	      </screen>
	    </para>

	    <para>The <option>-m</option> gives detailed information about
	      only the current user. Passing any two arguments to
	      <command>who</command> is the equivalent of <command>who
	      -m</command>, as in <command>who am i</command> or <command>who
	      The Man</command>.</para> 
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>who -m</userinput>
<computeroutput>localhost.localdomain!bozo  pts/2    Apr 27 17:49</computeroutput>
	      </screen>
	    </para>


	    <para><anchor id="whoamiref"><command>whoami</command> is similar to <command>who
	      -m</command>, but only lists the user name.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>whoami</userinput>
<computeroutput>bozo</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>w</command></term>
	  <indexterm>
	    <primary>w</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>w</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show all logged on users and the processes belonging to them. This is
	      an extended version of <command>who</command>. The output of <command>w</command>
	      may be piped to <command>grep</command> to find a specific user and/or process.</para>
	    <screen><prompt>bash$ </prompt><userinput>w | grep startx</userinput>
<computeroutput>bozo  tty1     -                 4:22pm  6:41   4.47s  0.45s  startx</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>logname</command></term>
	  <indexterm>
	    <primary>logname</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>logname</secondary>
	  </indexterm>
	  <listitem>

	    <para>Show current user's login name (as found in
	      <filename>/var/run/utmp</filename>). This is a
	      near-equivalent to <link linkend="whoamiref">whoami</link>,
	      above.</para>

	    <screen><prompt>bash$ </prompt><userinput>logname</userinput>
<computeroutput>bozo</computeroutput>

<prompt>bash$ </prompt><userinput>whoami</userinput>
<computeroutput>bozo</computeroutput></screen>	    

            <para>However...</para>

	    <screen><prompt>bash$ </prompt><userinput>su</userinput>
<computeroutput>Password: ......</computeroutput>

<prompt>bash# </prompt><userinput>whoami</userinput>
<computeroutput>root</computeroutput>
<prompt>bash# </prompt><userinput>logname</userinput>
<computeroutput>bozo</computeroutput></screen>	    

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="suref"><command>su</command></term>
	  <indexterm>
	    <primary>su</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>su</secondary>
	  </indexterm>
	  <listitem>
	    <para>Runs a program or script as a
	      <emphasis>s</emphasis>ubstitute <emphasis>u</emphasis>ser.
	      <command>su rjones</command> starts a shell as user
	      <emphasis>rjones</emphasis>. A naked <command>su</command>
	      defaults to <emphasis>root</emphasis>.  See <xref
	      linkend="fifo">.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sudo</command></term>
	  <indexterm>
	    <primary>sudo</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>sudo</secondary>
	  </indexterm>
	  <listitem>
	    <para>Runs a command as root (or another user). This may
	      be used in a script, thus permitting a regular user to
	      run the script.</para>

	      <para><programlisting>#!/bin/bash

# Some commands.
sudo cp /root/secretfile /home/bozo/secret
# Some more commands.</programlisting></para>
	    
	    <para>The file <filename>/etc/sudoers</filename> holds
	      the names of users permitted to invoke
	      <command>sudo</command>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>passwd</command></term>
	  <indexterm>
	    <primary>passwd</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>password</secondary>
	  </indexterm>
	  <listitem>

	    <para>Sets or changes a user's password.</para>

	    <para>The <command>passwd</command> can be used in a script, but
	      <emphasis>should not</emphasis> be.
	        <programlisting>#!/bin/bash
#  set-new-password.sh: Not a good idea.
#  This script must be run as root,
#+ or better yet, not run at all.

ROOT_UID=0         # Root has $UID 0.
E_WRONG_USER=65    # Not root?

if [ "$UID" -ne "$ROOT_UID" ]
then
  echo; echo "Only root can run this script."; echo
  exit $E_WRONG_USER
else
  echo; echo "You should know better than to run this script, root."
fi  


username=bozo
NEWPASSWORD=security_violation

echo "$NEWPASSWORD" | passwd --stdin "$username"
#  The '--stdin' option to 'passwd' permits
#+ getting new password from stdin (or a pipe).

echo; echo "User $username's password changed!"

# Using the 'passwd' command in a script is dangerous.

exit 0</programlisting>
            </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>ac</command></term>
	  <indexterm>
	    <primary>ac</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>accounting</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show users' logged in time, as read from
	      <filename>/var/log/wtmp</filename>. This is one of the GNU
	      accounting utilities.</para>
	    <screen><prompt>bash$ </prompt><userinput>ac</userinput>
<computeroutput>        total       68.08</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>last</command></term>
	  <indexterm>
	    <primary>last</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>logged in</secondary>
	  </indexterm>
	  <listitem>
	    <para>List <emphasis>last</emphasis> logged in users, as read from
	      <filename>/var/log/wtmp</filename>. This command can also
	      show remote logins.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>newgrp</command></term>
	  <indexterm>
	    <primary>newgrp</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>group</secondary>
	  </indexterm>
	  <listitem>
	    <para>Change user's group ID without logging out. This permits
	      access to the new group's files. Since users may be
	      members of multiple groups simultaneously, this command
	      finds little use.</para>
	  </listitem>
	</varlistentry>

      </variablelist>


      <variablelist id="terminalssys">
        <title><anchor id="terminalssys1">Terminals</title>

	<varlistentry>
	  <term><command>tty</command></term>
	  <indexterm>
	    <primary>tty</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tty</secondary>
	  </indexterm>
	  <listitem>
	    <para>Echoes the name of the current user's terminal.
	      Note that each separate xterm window counts as a different
	      terminal.</para>
	    <screen><prompt>bash$ </prompt><userinput>tty</userinput>
<computeroutput>/dev/pts/1</computeroutput></screen>
	      
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="sttyref"><command>stty</command></term>
	  <indexterm>
	    <primary>stty</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>stty</secondary>
	  </indexterm>
	  <listitem>
	    <para>Shows and/or changes terminal settings. This complex
	      command, used in a script, can control terminal behavior
	      and the way output displays. See the info page, and study
	      it carefully.</para>

	    <example id="erase">
	      <title>Setting an erase character</title>
	      <programlisting>&erase;</programlisting>
	    </example>

	    <example id="secretpw">
	      <title><command>secret password</command>:
	      Turning off terminal echoing </title>
	      <programlisting>&secretpw;</programlisting>
	    </example>

	    <para>A creative use of <command>stty</command> is detecting a
	      user keypress (without hitting
	      <keycap>ENTER</keycap>).</para>

	    <example id="keypress">
	      <title>Keypress detection</title>
	      <programlisting>&keypress;</programlisting>
	    </example>

	    <para>Also see <xref linkend="timeout">.</para>


	    <sidebar><title>terminals and modes</title>

	    <para>Normally, a terminal works in the
	      <emphasis>canonical</emphasis> mode.  When a user hits a
	      key, the resulting character does not immediately go to
	      the program actually running in this terminal.  A buffer
	      local to the terminal stores keystrokes. When the user
	      hits the <keycap>ENTER</keycap> key, this sends all the
	      stored keystrokes to the program running.  There is even
	      a basic line editor inside the terminal.</para>

	    <para>
	        <screen><prompt>bash$ </prompt><userinput>stty -a</userinput>
<computeroutput>speed 9600 baud; rows 36; columns 96; line = 0;
 intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = &lt;undef&gt;; eol2 = &lt;undef&gt;;
 start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O;
 ...
 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt</computeroutput>
                </screen>
	    </para>

            <para>Using canonical mode, it is possible to redefine the
              special keys for the local terminal line editor.

	        <screen>
<prompt>bash$ </prompt><userinput>cat > filexxx</userinput>
<userinput>wha&lt;ctl-W&gt;I&lt;ctl-H&gt;foo bar&lt;ctl-U&gt;hello world&lt;ENTER&gt;</userinput>
<userinput>&lt;ctl-D&gt;</userinput>
<prompt>bash$ </prompt><userinput>cat filexxx</userinput>
<computeroutput>hello world</computeroutput>		
<prompt>bash$ </prompt><userinput>bash$ wc -c < file</userinput>
<computeroutput>13</computeroutput>		
                </screen>

              The process controlling the terminal receives only 13
              characters (12 alphabetic ones, plus a newline), although
              the user hit 26 keys.
            </para>

            <para>In non-canonical (<quote>raw</quote>) mode, every
              key hit (including special editing keys such as
              <keycap>ctl-H</keycap>) sends a character immediately to
              the controlling process.</para>


            <para>The Bash prompt disables both <option>icanon</option>
              and <option>echo</option>, since it replaces the basic
              terminal line editor with its own more elaborate one. For
              example, when you hit <keycap>ctl-A</keycap> at the Bash
              prompt, there's no <keycap>^A</keycap> echoed by the
              terminal, but Bash gets a <keycap>\1</keycap> character,
              interprets it, and moves the cursor to the begining of
              the line.</para>

	    <para><emphasis>Stephane Chazelas</emphasis></para>  

	    </sidebar>


	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>tset</command></term>
	  <indexterm>
	    <primary>tset</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>tset</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show or initialize terminal settings. 
	      This is a less capable version of
	      <command>stty</command>.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>tset -r</userinput>
<computeroutput>Terminal type is xterm-xfree86.
 Kill is control-U (^U).
 Interrupt is control-C (^C).</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>setserial</command></term>
	  <indexterm>
	    <primary>setserial</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>serial</secondary>
	  </indexterm>
	  <listitem>

	    <para>Set or display serial port parameters. This command must be
	      run by root user and is usually found in a system setup
	      script.</para>

	    <para><programlisting># From /etc/pcmcia/serial script:

IRQ=`setserial /dev/$DEVICE | sed -e 's/.*IRQ: //'`
setserial /dev/$DEVICE irq 0 ; setserial /dev/$DEVICE irq $IRQ</programlisting></para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>getty</command></term>
	  <term><command>agetty</command></term>
	  <indexterm>
	    <primary>getty</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>getty</secondary>
	  </indexterm>
	  <indexterm>
	    <primary>agetty</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>agetty</secondary>
	  </indexterm>
	  <listitem>
	    <para>The initialization process for a terminal uses
	      <command>getty</command> or <command>agetty</command>
	      to set it up for login by a user. These commands are not
	      used within user shell scripts. Their scripting counterpart
	      is <command>stty</command>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="mesgref"><command>mesg</command></term>
	  <indexterm>
	    <primary>mesg</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>mesg</secondary>
	  </indexterm>
	  <listitem>
	    <para>Enables or disables write access to the current user's
	      terminal.  Disabling access would prevent another user
	      on the network to <link linkend="writeref">write</link>
	      to the terminal.</para>

	    <tip><para>It can be very annoying to have a message
	      about ordering pizza suddenly appear in the middle of
	      the text file you are editing. On a multi-user network,
	      you might therefore wish to disable write access to your
	      terminal when you need to avoid interruptions.</para></tip>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>wall</command></term>
	  <indexterm>
	    <primary>wall</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>wall</secondary>
	  </indexterm>
	  <listitem>
	    <para>This is an acronym for <quote><link
	      linkend="writeref">write</link> all</quote>, i.e., sending
	      a message to all users at every terminal logged into the
	      network. It is primarily a system administrator's tool,
	      useful, for example, when warning everyone that the
	      system will shortly go down due to a problem (see <xref
	      linkend="ex70">).</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>wall System going down for maintenance in 5 minutes!</userinput>
<computeroutput>Broadcast message from bozo (pts/1) Sun Jul  8 13:53:27 2001...

 System going down for maintenance in 5 minutes!</computeroutput>
	      </screen>
	    </para>

	    <note><para>If write access to a particular terminal has been
	      disabled with <command>mesg</command>, then
	      <command>wall</command> cannot send a message to
	      it.</para></note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>dmesg</command></term>
	  <indexterm>
	    <primary>dmesg</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>dmesg</secondary>
	  </indexterm>
	  <listitem>
	    <para>Lists all system bootup messages to
	      <filename>stdout</filename>. Handy for debugging and
	      ascertaining which device drivers were installed
	      and which system interrupts in use. The output
	      of <command>dmesg</command> may, of course, be
	      parsed with <link linkend="grepref">grep</link>,
	      <link linkend="sedref">sed</link>, or <link
	      linkend="awkref">awk</link> from within a script.</para>
	  <para>
	      <screen><prompt>bash$ </prompt><userinput>dmesg | grep hda</userinput>
<computeroutput>Kernel command line: ro root=/dev/hda2
 hda: IBM-DLGA-23080, ATA DISK drive
 hda: 6015744 sectors (3080 MB) w/96KiB Cache, CHS=746/128/63
 hda: hda1 hda2 hda3 < hda5 hda6 hda7 > hda4</computeroutput>
	      </screen>
	    </para>
	  </listitem>
	</varlistentry>

      </variablelist>

      <variablelist id="statisticssys">
        <title><anchor id="statisticssys1">Information and Statistics</title>

	<varlistentry>
	  <term><command>uname</command></term>
	  <indexterm>
	    <primary>uname</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uname</secondary>
	  </indexterm>
	  <listitem>
	    <para>Output system specifications (OS, kernel version,
	      etc.) to <filename>stdout</filename>.  Invoked with the
	      <option>-a</option> option, gives verbose system info
	      (see <xref linkend="ex41">). The <option>-s</option>
	      option shows only the OS type.</para>

	    <screen><prompt>bash$ </prompt><userinput>uname -a</userinput>
<computeroutput>Linux localhost.localdomain 2.2.15-2.5.0 #1 Sat Feb 5 00:13:43 EST 2000 i686 unknown</computeroutput>

<prompt>bash$ </prompt><userinput>uname -s</userinput>
<computeroutput>Linux</computeroutput></screen>	    
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>arch</command></term>
	  <indexterm>
	    <primary>arch</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>arch</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show system architecture.
	      Equivalent to <command>uname -m</command>. See <xref
	      linkend="casecmd">.</para>
	    <screen><prompt>bash$ </prompt><userinput>arch</userinput>
<computeroutput>i686</computeroutput>

<prompt>bash$ </prompt><userinput>uname -m</userinput>
<computeroutput>i686</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>lastcomm</command></term>
	  <indexterm>
	    <primary>lastcomm</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>last</secondary>
	  </indexterm>
	  <listitem>
	    <para>Gives information about previous commands, as stored
	      in the <filename>/var/account/pacct</filename> file. Command
	      name and user name can be specified by options. This is
	      one of the GNU accounting utilities.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>lastlog</command></term>
	  <indexterm>
	    <primary>lastlog</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>last</secondary>
	  </indexterm>
	  <listitem>
	    <para>List the last login time of all system users. This
	      references the <filename>/var/log/lastlog</filename>
	      file.</para>
	    <para>
	      <screen><prompt>bash$ </prompt><userinput>lastlog</userinput>
<computeroutput>root          tty1                      Fri Dec  7 18:43:21 -0700 2001
 bin                                     **Never logged in**
 daemon                                  **Never logged in**
 ...
 bozo          tty1                      Sat Dec  8 21:14:29 -0700 2001</computeroutput>



<prompt>bash$ </prompt><userinput>lastlog | grep root</userinput>
<computeroutput>root          tty1                      Fri Dec  7 18:43:21 -0700 2001</computeroutput>
	      </screen>
	      </para>

	      <caution><para>This command will fail if the user invoking
		it does not have read permission for the
		<filename>/var/log/lastlog</filename> file.</para></caution>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>lsof</command></term>
	  <indexterm>
	    <primary>lsof</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>lsof</secondary>
	  </indexterm>
	  <listitem>
	    <para>List open files. This command outputs a detailed
	      table of all currently open files and gives information
	      about their owner, size, the processes associated with
	      them, and more. Of course, <command>lsof</command> may
	      be piped to <link linkend="grepref">grep</link> and/or
	      <link linkend="awkref">awk</link> to parse and analyze
	      its results.</para>

	  <para>
	      <screen><prompt>bash$ </prompt><userinput>lsof</userinput>
<computeroutput>COMMAND    PID    USER   FD   TYPE     DEVICE    SIZE     NODE NAME
 init         1    root  mem    REG        3,5   30748    30303 /sbin/init
 init         1    root  mem    REG        3,5   73120     8069 /lib/ld-2.1.3.so
 init         1    root  mem    REG        3,5  931668     8075 /lib/libc-2.1.3.so
 cardmgr    213    root  mem    REG        3,5   36956    30357 /sbin/cardmgr
 ...</computeroutput>
	      </screen>
	    </para>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>strace</command></term>
	  <indexterm>
	    <primary>strace</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>strace</secondary>
	  </indexterm>
	  <listitem>
	    <para>Diagnostic and debugging tool for tracing system
	      calls and signals. The simplest way of invoking it is
	      <command>strace COMMAND</command>.</para>

	    <para>
	    <screen><prompt>bash$ </prompt><userinput>strace df</userinput>
<computeroutput>execve("/bin/df", ["df"], [/* 45 vars */]) = 0
 uname({sys="Linux", node="bozo.localdomain", ...}) = 0
 brk(0)                                  = 0x804f5e4
 ...</computeroutput>
	    </screen>
	    </para>

	    <para>This is the Linux equivalent of
	      <command>truss</command>.</para> 

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>nmap</command></term>
	  <indexterm>
	    <primary>nmap</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>port scan</secondary>
	  </indexterm>
	  <listitem>
	    <para>Network port scanner. This command scans a server to
	      locate open ports and the services associated with those
	      ports. It is an important security tool for locking down
	      a network against hacking attempts.</para>
	    <para><programlisting>#!/bin/bash

SERVER=$HOST                           # localhost.localdomain (127.0.0.1).
PORT_NUMBER=25                         # SMTP port.

nmap $SERVER | grep -w "$PORT_NUMBER"  # Is that particular port open?
#              grep -w matches whole words only,
#+             so this wouldn't match port 1025, for example.

exit 0

# 25/tcp     open        smtp</programlisting></para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="freeref"><command>free</command></term>
	  <indexterm>
	    <primary>free</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>free</secondary>
	  </indexterm>
	  <listitem>
	    <para>Shows memory and cache usage in tabular form. The
	      output of this command lends itself to parsing, using
	      <link linkend="grepref">grep</link>, <link
	      linkend="awkref">awk</link> or <command>Perl</command>. The
	      <command>procinfo</command> command shows all the
	      information that <command>free</command> does, and much
	      more.</para>

	    <screen><prompt>bash$ </prompt><command>free</command>
<computeroutput>                total       used       free     shared    buffers     cached
   Mem:         30504      28624       1880      15820       1608       16376
   -/+ buffers/cache:      10640      19864
   Swap:        68540       3128      65412</computeroutput></screen>

            <para>To show unused RAM memory:</para>
	    <screen><prompt>bash$ </prompt><command>free | grep Mem | awk '{ print $4 }'</command>
<computeroutput>1880</computeroutput></screen>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="procinforef"><command>procinfo</command></term>
	  <indexterm>
	    <primary>procinfo</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>procinfo</secondary>
	  </indexterm>
	  <listitem>
	    <para>Extract and list information and statistics from the
	      <link linkend="devprocref"><filename
	      class="directory">/proc</filename>
	      pseudo-filesystem</link>. This gives a very extensive and
	      detailed listing.</para>

	    <screen><prompt>bash$ </prompt><userinput>procinfo | grep Bootup</userinput>
<computeroutput>Bootup: Wed Mar 21 15:15:50 2001    Load average: 0.04 0.21 0.34 3/47 6829</computeroutput>
</screen>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="lsdevref"><command>lsdev</command></term>
	  <indexterm>
	    <primary>lsdev</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>device</secondary>
	  </indexterm>
	  <listitem>
	    <para>List devices, that is, show installed hardware.</para>
	      <para>
	      <screen><prompt>bash$ </prompt><userinput>lsdev</userinput>
<computeroutput>Device            DMA   IRQ  I/O Ports
 ------------------------------------------------
 cascade             4     2 
 dma                          0080-008f
 dma1                         0000-001f
 dma2                         00c0-00df
 fpu                          00f0-00ff
 ide0                     14  01f0-01f7 03f6-03f6
 ...</computeroutput>
	      </screen>
	      </para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="duref"><command>du</command></term>
	  <indexterm>
	    <primary>du</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>du</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show (disk) file usage, recursively. Defaults to current
	      working directory, unless otherwise specified.</para>

	    <screen><prompt>bash$ </prompt><command>du -ach</command>
<computeroutput>1.0k    ./wi.sh
 1.0k    ./tst.sh
 1.0k    ./random.file
 6.0k    .
 6.0k    total</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="dfref"><command>df</command></term>
	  <indexterm>
	    <primary>df</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>df</secondary>
	  </indexterm>
	  <listitem>
	    <para>Shows filesystem usage in tabular form.</para>

	    <screen><prompt>bash$ </prompt><command>df</command>
<computeroutput>Filesystem           1k-blocks      Used Available Use% Mounted on
 /dev/hda5               273262     92607    166547  36% /
 /dev/hda8               222525    123951     87085  59% /home
 /dev/hda7              1408796   1075744    261488  80% /usr</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>stat</command></term>
	  <indexterm>
	    <primary>stat</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>stat</secondary>
	  </indexterm>
	  <listitem>
	    <para>Gives detailed and verbose <emphasis>stat</emphasis>istics 
	      on a given file (even a directory or device file) or set
	      of files.</para>
	    <para>
	      <screen><prompt>bash$ </prompt><userinput>stat test.cru</userinput>
<computeroutput>  File: "test.cru"
   Size: 49970        Allocated Blocks: 100          Filetype: Regular File
   Mode: (0664/-rw-rw-r--)         Uid: (  501/ bozo)  Gid: (  501/ bozo)
 Device:  3,8   Inode: 18185     Links: 1    
 Access: Sat Jun  2 16:40:24 2001
 Modify: Sat Jun  2 16:40:24 2001
 Change: Sat Jun  2 16:40:24 2001</computeroutput>
	      </screen>
	    </para>

	    <para>If the target file does not exist, <command>stat</command>
	      returns an error message.</para>

	    <para>
	      <screen><prompt>bash$ </prompt><userinput>stat nonexistent-file</userinput>
<computeroutput>nonexistent-file: No such file or directory</computeroutput>
	      </screen>
	    </para>


	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="vmstatref"><command>vmstat</command></term>
	  <indexterm>
	    <primary>vmstat</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>virtual memory</secondary>
	  </indexterm>
	  <listitem>
	    <para>Display virtual memory statistics.</para>
	    <para>
	    <screen><prompt>bash$ </prompt><userinput>vmstat</userinput>
<computeroutput>   procs                      memory    swap          io system         cpu
 r  b  w   swpd   free   buff  cache  si  so    bi    bo   in    cs  us  sy id
 0  0  0      0  11040   2636  38952   0   0    33     7  271    88   8   3 89</computeroutput>
	    </screen>
	    </para>
  
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>netstat</command></term>
	  <indexterm>
	    <primary>netstat</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>netstat</secondary>
	  </indexterm>
	  <listitem>
	    <para>Show current network statistics and information, 
	      such as routing tables and active connections. This utility
	      accesses information in <filename>/proc/net</filename>
	      (<xref linkend="devproc">). See <xref
	      linkend="constat">.</para>
	    <para><command>netstat -r</command> is equivalent to <link
	      linkend="routeref">route</link>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="uptimeref"><command>uptime</command></term>
	  <indexterm>
	    <primary>uptime</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>uptime</secondary>
	  </indexterm>
	  <listitem>
	    <para>Shows how long the system has been running, along with
	      associated statistics.</para>
	    <screen><prompt>bash$ </prompt><userinput>uptime</userinput>
<computeroutput>10:28pm  up  1:57,  3 users,  load average: 0.17, 0.34, 0.27</computeroutput></screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="hnameref"><command>hostname</command></term>
	  <indexterm>
	    <primary>hostname</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>hostname</secondary>
	  </indexterm>
	  <listitem>
	    <para>Lists the system's host name. This command sets the host
	      name in an <filename class="directory">/etc/rc.d</filename>
	      setup script (<filename>/etc/rc.d/rc.sysinit</filename>
	      or similar).  It is equivalent to <command>uname
	      -n</command>,  and a counterpart to the <link
	      linkend="hostnameref">$HOSTNAME</link> internal
	      variable.</para>

	    <screen><prompt>bash$ </prompt><userinput>hostname</userinput>
<computeroutput>localhost.localdomain</computeroutput>

<prompt>bash$ </prompt><userinput>echo $HOSTNAME</userinput>
<computeroutput>localhost.localdomain</computeroutput></screen>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><anchor id="hostidref"><command>hostid</command></term>
	  <indexterm>
	    <primary>hostid</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>host id</secondary>
	  </indexterm>
	  <listitem>

	    <para>Echo a 32-bit hexadecimal numerical identifier for the
	      host machine.</para>

	    <para>
	      <screen><prompt>bash$ </prompt><userinput>hostid</userinput>
<computeroutput>7f0100</computeroutput></screen>
	    </para>

	    <note>
	    <para>This command allegedly fetches a <quote>unique</quote>
	      serial number for a particular system. Certain
	      product registration procedures use this number
	      to brand a particular user license. Unfortunately,
	      <command>hostid</command> only returns the machine
	      network address in hexadecimal, with pairs of bytes
	      transposed.</para>

	    <para>The network address of a typical non-networked Linux
	      machine, is found in <filename>/etc/hosts</filename>.</para>

	    <para>
	      <screen><prompt>bash$ </prompt><userinput>cat /etc/hosts</userinput>
<computeroutput>127.0.0.1               localhost.localdomain localhost</computeroutput>
</screen>
	    </para>

	    <para>As it happens, transposing the bytes of
	      <userinput>127.0.0.1</userinput>, we get
	      <userinput>0.127.1.0</userinput>, which translates in
	      hex to <userinput>007f0100</userinput>, the exact equivalent
	      of what <command>hostid</command> returns, above. There
	      exist only a few million other Linux machines with this
	      identical <emphasis>hostid</emphasis>.</para>
	    </note>

	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>sar</command></term>
	  <indexterm>
	    <primary>sar</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command</primary>
	    <secondary>system activity report</secondary>
	  </indexterm>
	  <listitem>
	    <para>Invoking <command>sar</command> (System Activity Reporter)
	      gives a very detailed rundown on system statistics. The
	      Santa Cruz Operation (SCO) released
	      <command>sar</command> as Open Source in June, 1999.</para>

	    <para>This command is not part of the base Linux distribution,
	      but may be obtained as part of the<ulink
	      url="http://perso.wanadoo.fr/sebastien.godard/">
	      sysstat utilities</ulink> package, written by <ulink
	      url="mailto:sebastien.godard@wanadoo.fr">Sebastien
	      Godard</ulink>.</para>

	    <screen>
<prompt>bash$ </prompt><userinput>sar</userinput>
<computeroutput>Linux 2.4.7-10 (localhost.localdomain) 	12/31/2001

 10:30:01 AM       CPU     %user     %nice   %system     %idle
 10:40:00 AM       all      1.39      0.00      0.77     97.84
 10:50:00 AM       all     76.83      0.00      1.45     21.72
 11:00:00 AM       all      1.32      0.00      0.69     97.99
 11:10:00 AM       all      1.17      0.00      0.30     98.53
 11:20:00 AM       all      0.51      0.00      0.30     99.19
 06:30:00 PM       all    100.00      0.00    100.01      0.00
 Average:          all      1.39      0.00      0.66     97.95</computeroutput>
           </screen>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><command>readelf</command></term>
	  <indexterm>
	    <primary>elf</primary>
	  </indexterm>
	  <indexterm>
	    <primary>command<
