This commit is contained in:
gferg 2005-06-05 14:39:50 +00:00
parent a748bd3591
commit 95201486ee
24 changed files with 572 additions and 274 deletions

View File

@ -6,6 +6,71 @@
http://personal.riverusers.com/~thegrendel/Change.log
------------------------------------------------------------------------
Version 3.5
Boxberry release, 06/05/05
1) In "Indirect References to Variables" section of "Variables Revisited" chapter:
Added "ugly kludge" sidebar.
2) In "Variable Assignment" section of "Introduction to Variables and
Parameters" chapter:
After "ex16.sh" example, noted that $(...) construct is a form of
command substitution.
3) In "Special Variable Types" section of "Introduction to Variables and
Parameters" chapter:
In note about remedies for missing command-line parameters,
added discussion about using parameter substitution,
rather than adding extra characters to variable names.
(Thank you, Fabian Kreutz.)
4) In "Command Substitution" chapter:
At note at end of chapter, added mention that nesting is possible
with $(...) construct, and added "agram2.sh" example script.
5) In "Internal Commands and Builtins" chapter:
At "exec" entry, added footnote and streamlined text.
6) In "File and Archiving Commands" section of "External Commands" Chapter:
At "more/less" entry, added "testing command sequence" usage example.
At "mktemp" entry, added usage example and elaborated existing example.
7) In "Communications Commands" section of "External Commands" chapter:
At "dig" entry, added "spam-lookup.sh" example.
8) In "Text Processing" section of "External Commands" Chapter:
At "tail" entry, added usage example of combining "head" and "tail"
to extract a specific line or lines from a text file.
9) In "System and Administrative Commands" chapter:
At "umask" entry, added "rot13a.sh" example script.
10) In "Complex Functions and Function Complexities" section of "Functions"
chapter:
Added in-line example ("days in month") of capturing function "echo"
as "return value."
11) In the "Shell Wrappers" section of "Miscellany" chapter:
Added "pr-asc.sh" example script.
12) Changed "Files" chapter into an appendix.
13) In the "Sed and Awk Micro-primer" appendix:
More examples of the awk "print" command.
14) In "Contributed Scripts" appendix:
Added "whx.sh" script.
(Thank you, Walter Dnes.)
15) Miscellaneous fixups and stylistic changes in the text and various
scripts.
Fixed up three misspellings of "permissible"!
Updated morethan.org site address.
Version 3.4
Teaberry release, 05/08/05
@ -259,7 +324,8 @@ Blueberry release, 02/06/05
3) In "Colorizing Scripts" section of "Miscellany" chapter:
Added link to Henry/teikedvl's utility for creating colorized scripts.
4) In "Complex Functions and Function Complexities" chapter:
4) In "Complex Functions and Function Complexities" section of "Functions"
chapter:
Added "func-cmdlinearg.sh" example script to clear up confusion
about command-line args passed to a script.

View File

@ -22,21 +22,21 @@ require no fixups to execute as expected.
Scripts needing to be altered:
-----------------------------
Du.sh
Du.sh (line 19)
encryptedpw.sh (lines 27 and 35)
ex57.sh
ex70.sh
ex71.sh
ex71a.sh
ex71b.sh
logevents.sh
m4.sh
pb.sh
pw.sh
read-r.sh
rnd.sh
rot13.sh
here-function.sh
ex57.sh (comment in line 8)
ex70.sh (line 3)
ex71.sh (line 7)
ex71a.sh (line 8)
ex71b.sh (line 22)
logevents.sh (lines 29, 36-39, 44, 53, 55, 60, 64)
m4.sh (line 8)
pw.sh (comment in line 4)
read-r.sh (lines 5, 6, 19, 26)
rnd.sh (comments in lines 38, 55, 64)
rot13.sh (comment, line 6)
rot13a.sh (comment, line 5)
here-function.sh (line 16)
avoid-subshell.sh (lines 24, 25, and 33)
usb.sh (line 28)
prepend.sh (lines 18 and 28)
@ -59,3 +59,5 @@ Hash.lib, (comments in lines lines 103 and 116: & --> &)
(comment in line 3: < --> &lt;, > --> &gt;)
hash-example.sh (comment in line 3: < --> &lt;, > --> &gt;)
quote-fetch.sh (comment in line 26: &amp; --> &)
ftpget.sh (comment in line 28)
whx.sh (comment in line 230)

View File

@ -140,6 +140,7 @@ Uncomment line below to generate index.
<!ENTITY lookup SYSTEM "lookup.sh">
<!ENTITY arglist SYSTEM "arglist.sh">
<!ENTITY rot13 SYSTEM "rot13.sh">
<!ENTITY rot13a SYSTEM "rot13a.sh">
<!ENTITY rot14 SYSTEM "rot14.sh">
<!ENTITY filecomp SYSTEM "file-comparison.sh">
<!ENTITY adddrv SYSTEM "add-drive.sh">
@ -260,6 +261,7 @@ Uncomment line below to generate index.
<!ENTITY factr SYSTEM "factr.sh">
<!ENTITY cannon SYSTEM "cannon.sh">
<!ENTITY agram SYSTEM "agram.sh">
<!ENTITY agram2 SYSTEM "agram2.sh">
<!ENTITY poem SYSTEM "poem.sh">
<!ENTITY soundex SYSTEM "soundex.sh">
<!ENTITY tempfilename SYSTEM "tempfile-name.sh">
@ -322,6 +324,9 @@ Uncomment line below to generate index.
<!ENTITY hashlib SYSTEM "Hash.lib">
<!ENTITY hashexample SYSTEM "hash-example.sh">
<!ENTITY getoptsimple SYSTEM "getopt-simple.sh">
<!ENTITY prasc SYSTEM "pr-asc.sh">
<!ENTITY whx SYSTEM "whx.sh">
<!ENTITY spamlookup SYSTEM "spam-lookup.sh">
<!ENTITY gen0data SYSTEM "gen0">
<!ENTITY cdll SYSTEM "cdll">
<!ENTITY bashrc SYSTEM "bashrc">
@ -342,19 +347,12 @@ Uncomment line below to generate index.
</affiliation>
</author>
<releaseinfo>3.4</releaseinfo>
<pubdate>08 May 2005</pubdate>
<releaseinfo>3.5</releaseinfo>
<pubdate>05 June 2005</pubdate>
<revhistory>
<revision>
<revnumber>3.1</revnumber>
<date>14 Nov 2004</date>
<authorinitials>mc</authorinitials>
<revremark>'BAYBERRY' release: Bugfix update.</revremark>
</revision>
<revision>
<revnumber>3.2</revnumber>
<date>06 Feb 2005</date>
@ -376,6 +374,13 @@ Uncomment line below to generate index.
<revremark>'TEABERRY' release: Important Update.</revremark>
</revision>
<revision>
<revnumber>3.5</revnumber>
<date>04 June 2005</date>
<authorinitials>mc</authorinitials>
<revremark>'BOXBERRY' release: Important Update.</revremark>
</revision>
</revhistory>
@ -396,7 +401,7 @@ Uncomment line below to generate index.
introduction to programming concepts.</para>
<para><ulink
url="http://personal.riverusers.com/~thegrendel/abs-guide-3.4.tar.bz2">
url="http://personal.riverusers.com/~thegrendel/abs-guide-3.5.tar.bz2">
The latest update of this document</ulink>, as an archived, <link
linkend="bzipref">bzip2-ed</link> <quote>tarball</quote>
including both the SGML source and rendered HTML, may
@ -3047,7 +3052,9 @@ echo "$uninitialized" # 5
<para>Variable assignment using the <firstterm>$(...)</firstterm>
mechanism (a newer method than <link
linkend="backquotesref">backquotes</link>)</para>
linkend="backquotesref">backquotes</link>). This is
actually a form of <link linkend="commandsubref">command
substitution</link>.</para>
<para><programlisting># From /etc/rc.d/rc.local
R=$(cat /etc/redhat-release)
@ -3247,7 +3254,15 @@ variable1=${variable1_/_/}
if [ -z $1 ]
then
exit $E_MISSING_POS_PARAM
fi
fi
# However, as Fabian Kreutz points out,
#+ the above method may have unexpected side-effects.
# A better method is parameter substitution:
# ${1:-$DefaultVal}
# See the "Parameter Substition" section
#+ in the "Variables Revisited" chapter.
</programlisting>
<para>---</para>
@ -4832,8 +4847,9 @@ home=/home/bozo
<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>
<para>Refer to <xref linkend="andor">, <xref linkend="twodim">,
and <xref linkend="whx"> to see compound comparison operators
in action.</para>
</sect1> <!-- Comparison operators (binary) -->
@ -8238,6 +8254,13 @@ echo $? # 1
(see <xref linkend="ex78">) makes indirect referencing more
intuitive.</para></caution>
<sidebar>
<para>Bash does not support pointer arithmetic, and this severely
limits the usefulness of indirect referencing. In fact, indirect
referencing in a scripting language is an ugly kludge.</para>
</sidebar>
</sect1> <!-- Indirect References to Variables -->
@ -8416,16 +8439,17 @@ rnumber=$(((RANDOM%30/3+1)*3))
<title>Loops and Branches</title>
<para>Operations on code blocks are the key to structured, organized
<para>Operations on code blocks are the key to structured and organized
shell scripts. Looping and branching constructs provide the tools for
accomplishing this.</para>
<sect1 id="loops1">
<title>Loops</title>
<para>A <firstterm>loop</firstterm> is a block of code that iterates
(repeats) a list of commands as long as the <firstterm>loop
control condition</firstterm> is true.</para>
<para>A <firstterm>loop</firstterm> is a block of code that
<firstterm>iterates</firstterm> (repeats) a list of commands
as long as the <firstterm>loop control condition</firstterm>
is true.</para>
<variablelist id="forloopref">
@ -8469,11 +8493,11 @@ rnumber=$(((RANDOM%30/3+1)*3))
<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 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
# In pass N of the loop, arg = $varN
# Arguments in [list] quoted to prevent possible word splitting.</programlisting></para>
@ -8501,11 +8525,11 @@ rnumber=$(((RANDOM%30/3+1)*3))
<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>
processing parameters in groups. In such cases,
use the <link linkend="setref">set</link> 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
@ -10193,16 +10217,19 @@ shift $(($OPTIND - 1))
</indexterm>
<listitem>
<para>This shell builtin replaces the current process with
<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>
the <command>exec</command>'ed command terminates.
<footnote><para>Unless the <command>exec</command> is used
to <link linkend="usingexecref">reassign file
descriptors</link>.</para></footnote>
</para>
<example id="ex54">
<title>Effects of <command>exec</command></title>
@ -10214,11 +10241,11 @@ shift $(($OPTIND - 1))
<programlisting>&selfexec;</programlisting>
</example>
<para>An <command>exec</command> also serves to reassign <link
linkend="fdref">file descriptors</link>. <userinput>exec
<para>An <command>exec</command> also serves to <link
linkend="usingexecref">reassign
file descriptors</link>. For example, <userinput>exec
&lt;zzz-file</userinput> replaces <filename>stdin</filename>
with the file <filename>zzz-file</filename> (see <xref
linkend="redir1">).</para>
with the file <filename>zzz-file</filename>.</para>
<note><para>The <option>-exec</option> option to
<link linkend="findref">find</link> is
@ -11392,12 +11419,12 @@ chmod u+s filename
<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).</para>
each file that <command>find</command> matches. The
command sequence terminates with <token>;</token> (the
<quote>;</quote> is <link linkend="escp">escaped</link> to
make certain the shell passes it to <command>find</command>
literally, without interpreting it as a special character).</para>
<para>
<screen><prompt>bash$ </prompt><userinput>find ~/ -name '*.txt'</userinput>
@ -12380,6 +12407,21 @@ done
<programlisting>&ex12;</programlisting>
</example>
<tip>
<para>To list a specific line of a text file,
<link linkend="piperef">pipe</link> the output of
<command>head</command> to <command>tail -1</command>.
For example <userinput>head -8 database.txt | tail
-1</userinput> lists the 8th line of the file
<filename>database.txt</filename>.</para>
<para>To set a variable to a given block of a text file:
<programlisting>var=$(head -$m $filename | tail -$n)
# filename = name of file
# m = from beginning of file, number of lines to end of block
# n = number of lines to set variable to (trim from end of block)</programlisting></para>
</tip>
<para>See also <xref linkend="ex41">, <xref linkend="ex52"> and
<xref linkend="online">.</para>
@ -14501,15 +14543,39 @@ gzip -cd patchXX.gz | patch -p0
<secondary>filename</secondary>
</indexterm>
<listitem>
<para>Create a temporary file with a <quote>unique</quote>
filename.</para>
<para>Create a <firstterm>temporary file</firstterm>
<footnote><para>Creates a temporary
<emphasis>directory</emphasis> when invoked with the
<option>-d</option> option.</para></footnote>
with a <quote>unique</quote> filename. When invoked
from the command line without additional arguments,
it creates a zero-length file in the <filename
class="directory">/tmp</filename> directory.</para>
<para>
<screen><prompt>bash$ </prompt><userinput>mktemp</userinput>
<computeroutput>/tmp/tmp.zzsvql3154</computeroutput>
</screen>
</para>
<para><programlisting>PREFIX=filename
tempfile=`mktemp $PREFIX.XXXXXX`
# ^^^^^^ Need at least 6 placeholders
#+ in the filename template.
# If no filename template supplied,
#+ "tmp.XXXXXXXXXX" is the default.
echo "tempfile name = $tempfile"
# tempfile name = filename.QA2ZpY
# or something similar...</programlisting></para>
# or something similar...
# Creates a file of that name in the current working directory
#+ with 600 file permissions.
# A "umask 177" is therefore unnecessary,
# but it's good programming practice anyhow.</programlisting></para>
</listitem>
</varlistentry>
@ -14606,9 +14672,24 @@ echo "tempfile name = $tempfile"
<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>
These may be used to filter the output of
<filename>stdout</filename> . . . or of a script.</para>
<para>
An interesting application of <command>more</command>
is to <quote>test drive</quote> a command sequence,
to forestall potentially unpleasant consequences.
<programlisting>ls /home/bozo | awk '{print "rm -rf " $1}' | more
# ^^^^
# Testing the effect of the following (disastrous) command line:
# ls /home/bozo | awk '{print "rm -rf " $1}' | sh
# Hand off to the shell to execute . . . ^^</programlisting>
</para>
</listitem>
</varlistentry>
@ -14752,8 +14833,13 @@ echo "tempfile name = $tempfile"
</screen>
</para>
<example id="spamlookup">
<title>Finding out where to report a spammer</title>
<programlisting>&spamlookup;</programlisting>
</example>
<example id="isspammer">
<title>Checking a spam domain</title>
<title>Analyzing a spam domain</title>
<programlisting>&isspammer;</programlisting>
</example>
@ -14843,7 +14929,7 @@ echo "tempfile name = $tempfile"
<para>Perform a DNS (Domain Name System) lookup.
The <option>-h</option> option permits specifying which
particular <emphasis>whois</emphasis> server to query. See
<xref linkend="ex18">.</para>
<xref linkend="ex18"> and <xref linkend="spamlookup">.</para>
</listitem>
</varlistentry>
@ -19119,18 +19205,20 @@ exit 0 # Will not exit here, because this script will never terminate.</pr
</indexterm>
<term><anchor id="umaskref"><command>umask</command></term>
<listitem>
<para>User file creation MASK. Limit the default file attributes
for a particular user. All files created by that user take
on the attributes specified by <command>umask</command>. The
(octal) value passed to <command>umask</command> defines the
file permissions <emphasis>disabled</emphasis>. For example,
<command>umask 022</command> ensures that new files will
have at most 755 permissions (777 NAND 022).
<para>User file creation permissions
<firstterm>mask</firstterm>. Limit the default file
attributes for a particular user. All files created
by that user take on the attributes specified by
<command>umask</command>. The (octal) value passed to
<command>umask</command> defines the file permissions
<firstterm>disabled</firstterm>. For example, <command>umask
022</command> ensures that new files will have at most
755 permissions (777 NAND 022).
<footnote><para>NAND is the logical
<firstterm>not-and</firstterm> operator. Its effect
is somewhat similar to subtraction.</para></footnote>
<footnote><para>NAND is the logical <quote>not-and</quote>
operator. Its effect is somewhat similar to
subtraction.</para></footnote>
Of course, the user may later change the
attributes of particular files with <link
linkend="chmodref">chmod</link>. The usual practice
@ -19139,6 +19227,12 @@ exit 0 # Will not exit here, because this script will never terminate.</pr
<filename>~/.bash_profile</filename> (see <xref
linkend="files">).</para>
<example id="rot13a">
<title>Using <command>umask</command> to hide an output file
from prying eyes</title>
<programlisting>&rot13a;</programlisting>
</example>
</listitem>
</varlistentry>
@ -19746,6 +19840,19 @@ File_contents2=$(&lt;$file2) # Bash permits this also.</programlisting></
</screen>
</para>
<para>Unlike backticks, the <command>$(...)</command> form of
command substitution permits nesting.</para>
<para><programlisting>word_count=$( wc -w $(ls -l | awk '{print $9}') )</programlisting>
</para>
<para>Or, for something a bit more elaborate . . .</para>
<example id="agram2">
<title>Finding anagrams</title>
<programlisting>&agram2;</programlisting>
</example>
</note>
@ -20099,6 +20206,8 @@ exec 3>&- # Now close it for the remainder of the s
<sect1><title>Using <command>exec</command></title>
<para><anchor id="usingexecref"></para>
<para>An <command>exec &lt;filename</command> command redirects
<filename>stdin</filename> to a file. From that point on, all
<filename>stdin</filename> comes from that file, rather than
@ -21898,7 +22007,7 @@ f2 ()
f1 # Function "f2" is not actually called until this point,
#+ although it is referenced before its definition.
# This is permissable.
# This is permissible.
# Thanks, S.C.</programlisting>
</para>
@ -21929,7 +22038,7 @@ f2 # Now, it's all right to call "f2",
<para>Function declarations can appear in unlikely places, even where a
command would otherwise go.
<programlisting>ls -l | foo() { echo "foo"; } # Permissable, but useless.
<programlisting>ls -l | foo() { echo "foo"; } # Permissible, but useless.
@ -22146,10 +22255,10 @@ echo "return value = $Return_Val" #25701</programlisting>
</para>
<para>An even more elegant method is to simply have the
function <command>echo</command> its <quote>return
value to <filename>stdout</filename>,</quote> and to
then capture it by <link linkend="commandsubref">command
<para>A more elegant method is to have the function
<command>echo</command> its <quote>return
value to <filename>stdout</filename>,</quote> and
then capture it by <link linkend="commandsubref">command
substitution</link>. See the <link linkend="rvt">discussion
of this</link> in <xref linkend="assortedtips">.</para>
@ -22158,6 +22267,32 @@ echo "return value = $Return_Val" #25701</programlisting>
<programlisting>&max2;</programlisting>
</example>
<para>Here is another example of capturing a function
<quote>return value.</quote> Understanding it requires some
knowledge of <link linkend="awkref">awk</link>.
<programlisting>month_length () # Takes month number as an argument.
{ # Returns number of days in month.
monthD="31 28 31 30 31 30 31 31 30 31 30 31" # Declare as local?
echo "$monthD" | awk '{ print $'"${1}"' }' # Tricky.
# ^^^^^^^^^
# Parameter passed to function ($1 -- month number), then to awk.
# Awk sees this as "print $1 . . . print $12" (depending on month number)
# Template for passing a parameter to embedded awk script:
# $'"${script_parameter}"'
# Needs error checking for correct parameter range (1-12)
#+ and for February in leap year.
}
# ----------------------------------------------
# Usage example:
month=4 # April, for example (4th month).
days_in=$(month_length $month)
echo $days_in # 30
# ----------------------------------------------</programlisting></para>
<para>See also <xref linkend="daysbetween">.</para>
<para><userinput>Exercise:</userinput> Using what we have
@ -22194,7 +22329,7 @@ echo "return value = $Return_Val" #25701</programlisting>
<programlisting>&realname;</programlisting>
</example>
<para>There is an alternative, and perhaps less confusing
<para>There is an alternate, and perhaps less confusing
method of redirecting a function's
<filename>stdin</filename>. This involves redirecting the
<filename>stdin</filename> to an embedded bracketed code
@ -22870,7 +23005,7 @@ exit 0</programlisting></para>
<para>--</para>
<para>Bash supports only one-dimensional arrays, however a little
<para>Bash supports only one-dimensional arrays, though a little
trickery permits simulating multi-dimensional ones.</para>
<example id="twodim">
@ -22879,96 +23014,25 @@ exit 0</programlisting></para>
</example>
<para>A two-dimensional array is essentially equivalent to a
one-dimensional one, but with additional addressing modes for
referencing and manipulating the individual elements by
<quote>row</quote> and <quote>column</quote> position.</para>
one-dimensional one, but with additional addressing modes
for referencing and manipulating the individual elements
by <emphasis>row</emphasis> and <emphasis>column</emphasis>
position.</para>
<para>For an even more elaborate example of simulating a
two-dimensional array, see <xref linkend="lifeslow">.</para>
<para>--</para>
<para>For yet another interesting script using arrays, see:
<itemizedlist>
<listitem><para><xref linkend="agram2"></para></listitem>
</itemizedlist>
</para>
</chapter> <!-- Arrays -->
<chapter id="files">
<title>Files</title>
<variablelist id="filesref">
<title><anchor id="filesref1">startup files</title>
<varlistentry>
<term></term>
<listitem>
<para>These files contain the aliases and <link
linkend="envref">environmental variables</link>
made available to Bash running as a user shell and to all
Bash scripts invoked after system initialization.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/profile</filename></term>
<listitem>
<para>systemwide defaults, mostly setting the environment
(all Bourne-type shells, not just Bash
<footnote><para>This does not apply to <command>csh</command>,
<command>tcsh</command>, and other shells not related to or
descended from the classic Bourne shell
(<command>sh</command>).</para></footnote>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/bashrc</filename></term>
<listitem>
<para>systemwide functions and <link
linkend="aliasref">aliases</link> for Bash</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename><varname>$HOME</varname>/.bash_profile</filename></term>
<listitem>
<para>user-specific Bash environmental default settings,
found in each user's home directory (the local counterpart
to <filename>/etc/profile</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename><varname>$HOME</varname>/.bashrc</filename></term>
<listitem>
<para>user-specific Bash init file, found in each user's home
directory (the local counterpart to
<filename>/etc/bashrc</filename>). Only interactive
shells and user scripts read this file. See
<xref linkend="sample-bashrc"> for a sample
<filename>.bashrc</filename> file.</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist id="logoutfileref">
<title><anchor id="logoutfileref1">logout file</title>
<varlistentry>
<term><filename><varname>$HOME</varname>/.bash_logout</filename></term>
<listitem>
<para>user-specific instruction file, found in
each user's home directory. Upon exit from a login (Bash)
shell, the commands in this file execute.</para>
</listitem>
</varlistentry>
</variablelist>
</chapter> <!-- Files -->
<chapter id="devproc">
<title>/dev and /proc</title>
@ -23260,7 +23324,7 @@ fi</programlisting></para>
<term>Uses of <filename>/dev/null</filename></term>
<listitem>
<para>Think of <filename>/dev/null</filename> as a <quote>black
hole</quote>. It is the nearest equivalent to a
hole.</quote> It is the nearest equivalent to a
write-only file. Everything written to it disappears
forever. Attempts to read or output from it result in
nothing. Nevertheless, <filename>/dev/null</filename>
@ -23302,7 +23366,7 @@ cat /dev/null > /var/log/wtmp</programlisting>
<para>Automatically emptying the contents of a logfile
(especially good for dealing with those nasty
<quote>cookies</quote> sent by Web commercial sites):</para>
<quote>cookies</quote> sent by commercial Web sites):</para>
<example id="cookies">
<title>Hiding the cookie jar</title>
@ -24367,8 +24431,8 @@ while [ "$index" -le "$MAXVAL" ]
...
E_NOTFOUND=75 # Uppercase for an errorcode,
# and name begins with "E_".
E_NOTFOUND=75 # Uppercase for an errorcode,
# +and name begins with "E_".
if [ ! -e "$filename" ]
then
echo "File $filename not found."
@ -24393,7 +24457,7 @@ favorite_number=$?
echo $favorite_number
_uservariable=23 # Permissable, but not recommended.
_uservariable=23 # Permissible, but not recommended.
# It's better for user-defined variables not to start with an underscore.
# Leave that for system variables.</programlisting>
</para>
@ -24652,8 +24716,13 @@ fi</programlisting>
<programlisting>&loggingwrapper;</programlisting>
</example>
<example id="coltotaler">
<example id="prasc">
<title> A <command>shell wrapper</command> around an awk script</title>
<programlisting>&prasc;</programlisting>
</example>
<example id="coltotaler">
<title> A <command>shell wrapper</command> around another awk script</title>
<programlisting>&coltotaler;</programlisting>
</example>
@ -25319,8 +25388,8 @@ exit 0</programlisting>
}
newstring=`capitalize_ichar "each sentence should start with a capital letter."`
echo "$newstring" # Each sentence should start with a capital letter.</programlisting>
newstring=`capitalize_ichar "every sentence should start with a capital letter."`
echo "$newstring" # Every sentence should start with a capital letter.</programlisting>
</para>
<para>It is even possible for a function to <quote>return</quote>
@ -25375,7 +25444,7 @@ echo "$newstring" # Each sentence should start with a capital letter.</
<varname>$PATH</varname> and <command>umask</command>.
<programlisting>#!/bin/bash
PATH=/bin:/usr/bin:/usr/local/bin ; export PATH
umask 022
umask 022 # Files that the script creates will have 755 permission.
# Thanks to Ian D. Allen, for this tip.</programlisting></para>
</listitem>
@ -25814,6 +25883,9 @@ else
# Or, ask for corrected input.
fi</programlisting></para>
<para>For another example of using the <command>=~</command>
operator, see <xref linkend="whx">.</para>
</listitem>
@ -26108,14 +26180,14 @@ fi</programlisting></para>
Chris Martin, Lee Maschmeyer, Bruno Haible, Wilbert Berendsen,
Sebastien Godard, Bj&ouml;n Eriksson, John MacDonald, Joshua
Tschida, Troy Engel, Manfred Schwarb, Amit Singh, Bill Gradwohl,
David Lombard, Jason Parker, Steve Parker, Bruce W. Clare,
William Park, Vernia Damiano, Mihai Maties, Jeremy Impson,
Ken Fuchs, Frank Wang, Sylvain Fourmanoit, Matthew Walker,
Kenny Stauffer, Filip Moritz, Andrzej Stefanski, Daniel Albers,
Stefano Palmeri, Nils Radtke, Jeroen Domburg, Alfredo Pironti,
Phil Braham, Bruno de Oliveira Schneider, Stefano Falsetto,
Chris Morgan, Linc Fessenden, Mariusz Gniazdowski, and David
Lawyer (himself an author of four HOWTOs).</para>
David Lombard, Jason Parker, Steve Parker, Bruce W. Clare, William
Park, Vernia Damiano, Mihai Maties, Jeremy Impson, Ken Fuchs,
Frank Wang, Sylvain Fourmanoit, Matthew Walker, Kenny Stauffer,
Filip Moritz, Andrzej Stefanski, Daniel Albers, Stefano Palmeri,
Nils Radtke, Jeroen Domburg, Alfredo Pironti, Phil Braham,
Bruno de Oliveira Schneider, Stefano Falsetto, Chris Morgan,
Walter Dnes, Linc Fessenden, Fabian Kreutz, Mariusz Gniazdowski,
and David Lawyer (himself an author of four HOWTOs).</para>
<para>My gratitude to <ulink url="mailto:chet@po.cwru.edu">Chet
Ramey</ulink> and Brian Fox for writing <firstterm>Bash</firstterm>,
@ -27128,6 +27200,15 @@ fi</programlisting></para>
<programlisting>&isspammer2;</programlisting>
</example>
<para>Another anti-spam script.</para>
<example id="whx">
<title>Spammer Hunt</title>
<programlisting>&whx;</programlisting>
</example>
<para><quote>Little Monster's</quote> front end to <link
linkend="wgetref">wget</link>.</para>
@ -28089,6 +28170,7 @@ pattern=BEGIN
<listitem><para><xref linkend="lifeslow"></para></listitem>
<listitem><para><xref linkend="selfdocument"></para></listitem>
<listitem><para><xref linkend="dictlookup"></para></listitem>
<listitem><para><xref linkend="whx"></para></listitem>
</orderedlist>
</para>
@ -28111,7 +28193,7 @@ pattern=BEGIN
for shell scripting.</para>
<para>Awk breaks each line of input passed to it into
<emphasis>fields</emphasis>. By default, a field is
<firstterm>fields</firstterm>. By default, a field is
a string of consecutive characters separated by <link
linkend="whitespaceref">whitespace</link>, though there are
options for changing the delimiter. Awk parses and operates on
@ -28122,7 +28204,14 @@ pattern=BEGIN
<para>Strong quoting (single quotes) and curly brackets enclose
segments of awk code within a shell script.</para>
<para><programlisting>awk '{print $3}' $filename
<para><programlisting>echo one two | awk '{print $1}'
# one
echo one two | awk '{print $2}'
# two
awk '{print $3}' $filename
# Prints field #3 of file $filename to stdout.
awk '{print $1 $5 $6}' $filename
@ -28169,6 +28258,7 @@ awk '{print $1 $5 $6}' $filename
<listitem><para><xref linkend="substringex"></para></listitem>
<listitem><para><xref linkend="sumproduct"></para></listitem>
<listitem><para><xref linkend="userlist"></para></listitem>
<listitem><para><xref linkend="prasc"></para></listitem>
</orderedlist>
</para>
@ -28204,79 +28294,82 @@ awk '{print $1 $5 $6}' $filename
<tbody>
<row>
<entry><option>1</option></entry>
<entry>catchall for general errors</entry>
<entry>Catchall for general errors</entry>
<entry>let "var1 = 1/0"</entry>
<entry>miscellaneous errors, such as <quote>divide by
<entry>Miscellaneous errors, such as <quote>divide by
zero</quote></entry>
</row>
<row>
<entry><option>2</option></entry>
<entry>misuse of shell builtins, according to Bash documentation</entry>
<entry>Misuse of shell builtins (according to Bash documentation)</entry>
<entry></entry>
<entry>Seldom seen, usually defaults to exit code 1</entry>
<entry>Seldom seen, usually defaults to exit code
<errorcode>1</errorcode></entry>
</row>
<row>
<entry><option>126</option></entry>
<entry>command invoked cannot execute</entry>
<entry>Command invoked cannot execute</entry>
<entry></entry>
<entry>permission problem or command is not an executable</entry>
<entry>Permission problem or command is not an executable</entry>
</row>
<row>
<entry><option>127</option></entry>
<entry><quote>command not found</quote></entry>
<entry></entry>
<entry>possible problem with <varname>$PATH</varname> or a typo</entry>
<entry>Possible problem with <varname>$PATH</varname> or a typo</entry>
</row>
<row>
<entry><option>128</option></entry>
<entry>invalid argument to <link linkend="exitcommandref">exit</link></entry>
<entry>Invalid argument to <link linkend="exitcommandref">exit</link></entry>
<entry>exit 3.14159</entry>
<entry><command>exit</command> takes only integer args in the
range 0 - 255 (see footnote)</entry>
range <returnvalue>0 - 255</returnvalue> (see
footnote)</entry>
</row>
<row>
<entry><option>128+n</option></entry>
<entry>fatal error signal <quote>n</quote></entry>
<entry>Fatal error signal <quote>n</quote></entry>
<entry><command>kill -9</command> <varname>$PPID</varname> of script</entry>
<entry><userinput>$?</userinput> returns 137 (128 + 9)</entry>
<entry><userinput>$?</userinput> returns
<errorcode>137</errorcode> (128 + 9)</entry>
</row>
<row>
<entry><option>130</option></entry>
<entry>script terminated by Control-C</entry>
<entry>Script terminated by Control-C</entry>
<entry></entry>
<entry>Control-C is fatal error signal 2, (130 = 128 + 2,
see above)</entry>
<entry>Control-C is fatal error signal
<errorcode>2</errorcode>, (130 = 128 + 2, see above)</entry>
</row>
<row>
<entry><option>255*</option></entry>
<entry>exit status out of range</entry>
<entry>exit -1</entry>
<entry>Exit status out of range</entry>
<entry>exit <returnvalue>-1</returnvalue></entry>
<entry><command>exit</command> takes only integer args in the
range 0 - 255</entry>
range <errorcode>0 - 255</errorcode></entry>
</row>
</tbody>
</tgroup>
</table>
<para>According to the table, exit codes <returnvalue>1 - 2, 126 -
165, and 255</returnvalue>
<para>According to the above table, exit codes <errorcode>1 - 2,
126 - 165, and 255</errorcode>
<footnote><para>Out of range exit values can result in
unexpected exit codes. An exit value greater than
<returnvalue>255</returnvalue> returns an exit code modulo
256. For example, <command>exit 3809</command> gives an
exit code of <errorcode>225</errorcode> (3809 % 256 =
225).</para></footnote>
unexpected exit codes. An exit value greater
than <errorcode>255</errorcode> returns an exit
code <link linkend="moduloref">modulo</link>
<errorcode>256</errorcode>. For example, <command>exit
3809</command> gives an exit code of <errorcode>225</errorcode>
(3809 % 256 = 225).</para></footnote>
have special meanings, and should therefore be avoided as
have special meanings, and should therefore be avoided for
user-specified exit parameters. Ending a script with <command>exit
127</command> would certainly cause confusion when troubleshooting
(is the error a <quote>command not found</quote> or a
(is the error code a <quote>command not found</quote> or a
user-defined one?). However, many scripts use an <command>exit
1</command> as a general bailout upon error. Since exit code
<returnvalue>1</returnvalue> signifies so many possible errors,
this might not add any additional ambiguity, but, on the other
hand, it probably would not be very informative either.</para>
<errorcode>1</errorcode> signifies so many possible errors,
this probably would not be helpful in debugging.</para>
<para>There has been an attempt to systematize exit status numbers
(see <filename
@ -28565,6 +28658,88 @@ exit 0</programlisting>
<!-- End Standard Command-Line Options appendix -->
<appendix id="files">
<title> Important Files</title>
<variablelist id="filesref">
<title><anchor id="filesref1">startup files</title>
<varlistentry>
<term></term>
<listitem>
<para>These files contain the aliases and <link
linkend="envref">environmental variables</link>
made available to Bash running as a user shell and to all
Bash scripts invoked after system initialization.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/profile</filename></term>
<listitem>
<para>systemwide defaults, mostly setting the environment
(all Bourne-type shells, not just Bash
<footnote><para>This does not apply to <command>csh</command>,
<command>tcsh</command>, and other shells not related to or
descended from the classic Bourne shell
(<command>sh</command>).</para></footnote>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>/etc/bashrc</filename></term>
<listitem>
<para>systemwide functions and <link
linkend="aliasref">aliases</link> for Bash</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename><varname>$HOME</varname>/.bash_profile</filename></term>
<listitem>
<para>user-specific Bash environmental default settings,
found in each user's home directory (the local counterpart
to <filename>/etc/profile</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename><varname>$HOME</varname>/.bashrc</filename></term>
<listitem>
<para>user-specific Bash init file, found in each user's home
directory (the local counterpart to
<filename>/etc/bashrc</filename>). Only interactive
shells and user scripts read this file. See
<xref linkend="sample-bashrc"> for a sample
<filename>.bashrc</filename> file.</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist id="logoutfileref">
<title><anchor id="logoutfileref1">logout file</title>
<varlistentry>
<term><filename><varname>$HOME</varname>/.bash_logout</filename></term>
<listitem>
<para>user-specific instruction file, found in
each user's home directory. Upon exit from a login (Bash)
shell, the commands in this file execute.</para>
</listitem>
</varlistentry>
</variablelist>
</appendix>
<!-- End Files appendix -->
<appendix id="systemdirs">
<title>Important System Directories</title>
@ -30571,6 +30746,11 @@ fairly detailed rundown on the Playfair Cipher and its solution methods.</progra
<entry>08 May 2005</entry>
<entry>TEABERRY release: Bugfixes, stylistic revisions.</entry>
</row>
<row>
<entry><option>3.5</option></entry>
<entry>05 Jun 2005</entry>
<entry>BOXBERRY release: Bugfixes, some materials added.</entry>
</row>
</tbody>
</tgroup>
</table>
@ -30597,7 +30777,7 @@ fairly detailed rundown on the Playfair Cipher and its solution methods.</progra
also mirrors the <emphasis>ABS Guide</emphasis>.</para>
<para>Yet another mirror site for this document is
<ulink url="ftp://ftp.morethan.org">the morethan.org ftp site</ulink>.</para>
<ulink url="http://www.morethan.org">morethan.org</ulink>.</para>
</appendix> <!-- Mirror Sites appendix -->

View File

@ -3,13 +3,15 @@
# Find anagrams of...
LETTERSET=etaoinshrdlu
FILTER='.......' # How many letters minimum?
# 1234567
anagram "$LETTERSET" | # Find all anagrams of the letterset...
grep '.......' | # With at least 7 letters,
grep "$FILTER" | # With at least 7 letters,
grep '^is' | # starting with 'is'
grep -v 's$' | # no plurals
grep -v 'ed$' # no past tense verbs
# Possible to add many combinations of conditions.
# Possible to add many combinations of conditions and filters.
# Uses "anagram" utility
#+ that is part of the author's "yawl" word list package.
@ -18,8 +20,20 @@ grep -v 'ed$' # no past tense verbs
exit 0 # End of code.
bash$ sh agram.sh
islander
isolate
isolead
isotheral
# Exercises:
# ---------
# Modify this script to take the LETTERSET as a command-line parameter.
# Parameterize the filters in lines 11 - 13 (as with $FILTER),
#+ so that they can be specified by passing arguments to a function.
# For a slightly different approach to anagramming,
#+ see the agram2.sh script.

View File

@ -4,8 +4,8 @@ ARGS=1 # Number of arguments expected.
E_BADARGS=65 # Exit value if incorrect number of args passed.
test $# -ne $ARGS && echo "Usage: `basename $0` $ARGS argument(s)" && exit $E_BADARGS
# If condition-1 true (wrong number of args passed to script),
# then the rest of the line executes, and script terminates.
# If condition 1 tests true (wrong number of args passed to script),
#+ then the rest of the line executes, and script terminates.
# Line below executes only if the above test fails.
echo "Correct number of arguments passed to this script."

View File

@ -14,7 +14,7 @@ var1=2367
echo "var1 declared as $var1"
var1=var1+1 # Integer declaration eliminates the need for 'let'.
echo "var1 incremented by 1 is $var1."
# Attempt to change variable declared as integer
# Attempt to change variable declared as integer.
echo "Attempting to change var1 to floating point value, 2367.1."
var1=2367.1 # Results in error message, with no change to variable.
echo "var1 is still $var1"

View File

@ -31,8 +31,8 @@ echo "Random number less than $RANGE --- $number"
echo
# If you need a random int greater than a lower bound,
# then set up a test to discard all numbers below that.
# If you need a random integer greater than a lower bound,
#+ then set up a test to discard all numbers below that.
FLOOR=200
@ -56,6 +56,7 @@ echo "Random number between $FLOOR and $RANGE --- $number"
echo
# Generate binary choice, that is, "true" or "false" value.
BINARY=2
T=1
@ -74,12 +75,13 @@ fi
echo
# Generate toss of the dice.
# Generate a toss of the dice.
SPOTS=6 # Modulo 6 gives range 0 - 5.
# Incrementing by 1 gives desired range of 1 - 6.
# Thanks, Paulo Marcel Coelho Aragao, for the simplification.
die1=0
die2=0
# Would it be better to just set SPOTS=7 and not add 1? Why or why not?
# Tosses each die separately, and so gives correct odds.
@ -88,6 +90,7 @@ die2=0
# Which arithmetic operation, above, has greater precedence --
#+ modulo (%) or addition (+)?
let "throw = $die1 + $die2"
echo "Throw of the dice = $throw"
echo

View File

@ -1,12 +1,12 @@
#!/bin/bash
echo
# Equivalent to:
while [ "$var1" != "end" ] # while test "$var1" != "end"
do # also works.
do
echo "Input variable #1 (end to exit) "
read var1 # Not 'read $var1' (why?).
echo "variable #1 = $var1" # Need quotes because of "#".
echo "variable #1 = $var1" # Need quotes because of "#" . . .
# If input is 'end', echoes it here.
# Does not test for termination condition until top of loop.
echo

View File

@ -16,3 +16,7 @@ tr a-z A-Z <"$1"
# Thanks, S.C.
exit 0
# Exercise:
# Rewrite this script to give the option of changing a file
#+ to *either* upper or lowercase.

View File

@ -6,14 +6,14 @@
# Try it with one two-word quoted command line parameter,
# ./scriptname "Mortimer Jones"
CMDLINEPARAM=1 # Expect at least command line parameter.
CMDLINEPARAM=1 # Expect at least command line parameter.
if [ $# -ge $CMDLINEPARAM ]
then
NAME=$1 # If more than one command line param,
# then just take the first.
NAME=$1 # If more than one command line param,
#+ then just take the first.
else
NAME="John Doe" # Default, if no command line parameter.
NAME="John Doe" # Default, if no command line parameter.
fi
RESPONDENT="the author of this fine script"

View File

@ -15,3 +15,6 @@ echo "Second line in $File is:"
echo "$line2"
exit 0
# Now, how do you parse the separate fields of each line?
# Hint: use awk.

View File

@ -2,6 +2,7 @@
# $Id$
# Script to perform batch anonymous ftp. Essentially converts a list of
# of command line arguments into input to ftp.
# ==> This script is nothing but a shell wrapper around "ftp" . . .
# Simple, and quick - written as a companion to ftplist
# -h specifies the remote host (default prep.ai.mit.edu)
# -d specifies the remote directory to cd to - you can provide a sequence
@ -24,8 +25,7 @@
# Obviously, the sequence of the options is important, since the equivalent
# commands are executed by ftp in corresponding order
#
# Mark Moraes (moraes@csri.toronto.edu), Feb 1, 1989
# ==> Angle brackets changed to parens, so Docbook won't get indigestion.
# Mark Moraes &lt;moraes@csri.toronto.edu&gt;, Feb 1, 1989
#
@ -35,6 +35,8 @@
# export PATH
# ==> Above 2 lines from original script probably superfluous.
E_BADARGS=65
TMPFILE=/tmp/ftp.$$
# ==> Creates temp file, using process id of script ($$)
# ==> to construct filename.
@ -51,10 +53,11 @@ set -f # So we can use globbing in -m
set x `getopt vh:d:c:m:f: $*`
if [ $? != 0 ]; then
echo $usage
exit 65
exit $E_BADARGS
fi
shift
trap 'rm -f ${TMPFILE} ; exit' 0 1 2 3 15
# ==> Delete tempfile in case of abnormal exit from script.
echo "user anonymous ${USER-gnu}@${SITE} > ${TMPFILE}"
# ==> Added quotes (recommended in complex echoes).
echo binary >> ${TMPFILE}
@ -74,17 +77,19 @@ do
echo get ${f1} ${f2} >> ${TMPFILE}; shift 2;;
--) shift; break;;
esac
# ==> 'lcd' and 'mget' are ftp commands. See "man ftp" . . .
done
if [ $# -ne 0 ]; then
echo $usage
exit 65 # ==> Changed from "exit 2" to conform with standard.
exit $E_BADARGS
# ==> Changed from "exit 2" to conform with style standard.
fi
if [ x${verbflag} != x ]; then
ftpflags="${ftpflags} -v"
fi
if [ x${remhost} = x ]; then
remhost=prep.ai.mit.edu
# ==> Rewrite to match your favorite ftp site.
# ==> Change to match appropriate ftp site.
fi
echo quit >> ${TMPFILE}
# ==> All commands saved in tempfile.

View File

@ -12,7 +12,9 @@
# Slightly modified and commented by ABS author.
#=================================================================#
# The Tower of Hanoi is an old mathematical puzzle.
# The Tower of Hanoi is a mathematical puzzle attributed to
#+ Edouard Lucas, a nineteenth-century French mathematician.
#
# There are three vertical posts set in a base.
# The first post has a set of annular rings stacked on it.
# These rings are flat disks with a hole drilled out of the center,

View File

@ -38,23 +38,23 @@ No_WSP=$'\x0A'$'\x0D'
# Field separator for dotted decimal ip addresses
ADR_IFS=${No_WSP}'.'
# Get the dns text resource record
# Get the dns text resource record.
# get_txt &lt;error_code&gt; &lt;list_query&gt;
get_txt() {
# parse $1 by assignment at the dots
# Parse $1 by assignment at the dots.
local -a dns
IFS=$ADR_IFS
dns=( $1 )
IFS=$WSP_IFS
if [ "${dns[0]}" == '127' ]
then
# see if there is a reason
# See if there is a reason.
echo $(dig +short $2 -t txt)
fi
}
# Get the dns address resource record
# Get the dns address resource record.
# chk_adr &lt;rev_dns&gt; &lt;list_server&gt;
chk_adr() {
local reply
@ -64,7 +64,7 @@ chk_adr() {
server=${1}${2}
reply=$( dig +short ${server} )
# if reply might be an error code . . .
# If reply might be an error code . . .
if [ ${#reply} -gt 6 ]
then
reason=$(get_txt ${reply} ${server} )

View File

@ -3,7 +3,7 @@
# $Id$
# Above line is RCS info.
# The latest version of this script is available from ftp://ftp.morethan.org.
# The latest version of this script is available from http://www.morethan.org.
#
# Spammer-identification
# by Michael S. Zick
@ -172,7 +172,7 @@ pend_dummy() { : ; }
pend_init() {
unset _pending_[@]
pend_func pend_stop_mark
_pend_hook_='pend_dummy' # Debug only
_pend_hook_='pend_dummy' # Debug only.
}
# Discard the top function on the stack.
@ -211,7 +211,7 @@ pend_release() {
_top_=${#_pending_[@]}-1
_pend_current_=${_pending_[$_top_]}
unset _pending_[$_top_]
$_pend_hook_ # Debug only
$_pend_hook_ # Debug only.
eval $_pend_current_
done
}
@ -969,7 +969,7 @@ name_fixup(){
IFS=${WSP_IFS}
_nf_end=${#_nf_tmp[@]}
case ${_nf_end} in
0) # No dots, only dots
0) # No dots, only dots.
echo
return 1
;;

View File

@ -1,10 +1,10 @@
#! /bin/bash
#!/bin/bash
#
# Changes every filename in working directory to all lowercase.
# Changes every filename in working directory to all lowercase.
#
# Inspired by a script of John Dubois,
# which was translated into into Bash by Chet Ramey,
# and considerably simplified by Mendel Cooper, author of this document.
# Inspired by a script of John Dubois,
#+ which was translated into Bash by Chet Ramey,
#+ and considerably simplified by the author of the ABS Guide.
for filename in * # Traverse all files in directory.
@ -17,7 +17,7 @@ do
fi
done
exit 0
exit $?
# Code below this line will not execute because of "exit".
@ -25,7 +25,6 @@ exit 0
# To run it, delete script above line.
# The above script will not work on filenames containing blanks or newlines.
# Stephane Chazelas therefore suggests the following alternative:
@ -41,4 +40,4 @@ do n=`echo "$filename/" | tr '[:upper:]' '[:lower:]'`
# Checks if filename already lowercase.
done
exit 0
exit $?

View File

@ -34,9 +34,11 @@ echo $retval # Echoes (to stdout), rather than returning value.
return_val=$(max2 33001 33997)
# ^^^^ Function name
# ^^^^^ ^^^^^ Params passed
# This is actually a form of command substitution:
#+ treating a function as if it were a command,
#+ and assigning the stdout of the function to the variable 'return_val.'
#+ and assigning the stdout of the function to the variable "return_val."
# ========================= OUTPUT ========================

View File

@ -1,6 +1,8 @@
#!/bin/bash
# logon.sh: A quick 'n dirty script to check whether you are on-line yet.
umask 177 # Make sure temp files are not world readable.
TRUE=1
LOGFILE=/var/log/messages
@ -8,6 +10,9 @@ LOGFILE=/var/log/messages
#+ (as root, chmod 644 /var/log/messages).
TEMPFILE=temp.$$
# Create a "unique" temp file name, using process id of the script.
# Using 'mktemp' is an alternative.
# For example:
# TEMPFILE=`mktemp temp.XXXXXX`
KEYWORD=address
# At logon, the line "remote IP address xxx.xxx.xxx.xxx"
# appended to /var/log/messages.

View File

@ -2,7 +2,7 @@
# pb.sh: phone book
# Written by Rick Boivie, and used with permission.
# Modifications by document author.
# Modifications by ABS Guide author.
MINARGS=1 # Script needs at least one argument.
DATAFILE=./phonebook

View File

@ -9,12 +9,12 @@
# The first 20 terms of the series are:
# 1 1 2 3 3 4 5 5 6 6 6 8 8 8 10 9 10 11 11 12
# See Hofstadter's book, "Goedel, Escher, Bach: An Eternal Golden Braid",
# p. 137, ff.
# See Hofstadter's book, "Goedel, Escher, Bach: An Eternal Golden Braid",
#+ p. 137, ff.
LIMIT=100 # Number of terms to calculate
LINEWIDTH=20 # Number of terms printed per line
LIMIT=100 # Number of terms to calculate.
LINEWIDTH=20 # Number of terms printed per line.
Q[1]=1 # First two terms of series are 1.
Q[2]=1
@ -26,8 +26,8 @@ echo -n "${Q[2]} "
for ((n=3; n <= $LIMIT; n++)) # C-like loop conditions.
do # Q[n] = Q[n - Q[n-1]] + Q[n - Q[n-2]] for n&gt;2
# Need to break the expression into intermediate terms,
# since Bash doesn't handle complex array arithmetic very well.
# Need to break the expression into intermediate terms,
#+ since Bash doesn't handle complex array arithmetic very well.
let "n1 = $n - 1" # n-1
let "n2 = $n - 2" # n-2
@ -42,7 +42,7 @@ Q[n]=`expr $T0 + $T1` # Q[n - Q[n-1]] + Q[n - Q[n-2]]
echo -n "${Q[n]} "
if [ `expr $n % $LINEWIDTH` -eq 0 ] # Format output.
then # mod
then # ^ Modula operator
echo # Break lines into neat chunks.
fi
@ -54,4 +54,4 @@ exit 0
# This is an iterative implementation of the Q-series.
# The more intuitive recursive implementation is left as an exercise.
# Warning: calculating this series recursively takes a *very* long time.
# Warning: calculating this series recursively takes a VERY long time.

View File

@ -4,15 +4,15 @@ echo
echo "Enter a string terminated by a \\, then press &lt;ENTER&gt;."
echo "Then, enter a second string, and again press &lt;ENTER&gt;."
read var1 # The "\" suppresses the newline, when reading "var1".
read var1 # The "\" suppresses the newline, when reading $var1.
# first line \
# second line
echo "var1 = $var1"
# var1 = first line second line
# For each line terminated by a "\",
# you get a prompt on the next line to continue feeding characters into var1.
# For each line terminated by a "\"
#+ you get a prompt on the next line to continue feeding characters into var1.
echo; echo

View File

@ -1,6 +1,7 @@
#!/bin/bash
# Starting the script with "#!/bin/bash -r"
# runs entire script in restricted mode.
# Starting the script with "#!/bin/bash -r"
#+ runs entire script in restricted mode.
echo

View File

@ -58,7 +58,7 @@ do #+ columns vary,
done
# The simpler equivalent is
# echo ${alpha[*]} | xargs -n $Columns
# echo ${alpha[*]} | xargs -n $Columns
echo
}
@ -67,7 +67,7 @@ filter () # Filter out negative array indices.
{
echo -n " " # Provides the tilt.
# Explain why.
# Explain how.
if [[ "$1" -ge 0 && "$1" -lt "$Rows" && "$2" -ge 0 && "$2" -lt "$Columns" ]]
then
@ -102,7 +102,8 @@ for (( row = Rows; row > -Rows; row-- ))
let "t2 = $column + $row"
fi
filter $t1 $t2 # Filter out negative array indices. Why?
filter $t1 $t2 # Filter out negative array indices.
# What happens if you don't do this?
done
echo; echo

View File

@ -10,11 +10,22 @@ echo "Just initialized \"\$variable\" to $variable."
let "variable *= 3"
echo "Just multiplied \"\$variable\" by 3."
# The "trap 'commands' DEBUG" construct would be more useful
# in the context of a complex script,
# where placing multiple "echo $variable" statements might be
# clumsy and time-consuming.
exit $?
# The "trap 'command1 . . . command2 . . .' DEBUG" construct is
#+ more appropriate in the context of a complex script,
#+ where placing multiple "echo $variable" statements might be
#+ clumsy and time-consuming.
# Thanks, Stephane Chazelas for the pointer.
exit 0
Output of script:
VARIABLE-TRACE> $variable = ""
VARIABLE-TRACE> $variable = "29"
Just initialized "$variable" to 29.
VARIABLE-TRACE> $variable = "29"
VARIABLE-TRACE> $variable = "87"
Just multiplied "$variable" by 3.
VARIABLE-TRACE> $variable = "87"