diff --git a/LDP/guide/docbook/abs-guide/Change.log b/LDP/guide/docbook/abs-guide/Change.log
index d3b52825..42775ccd 100644
--- a/LDP/guide/docbook/abs-guide/Change.log
+++ b/LDP/guide/docbook/abs-guide/Change.log
@@ -3,6 +3,59 @@ RELEASE HISTORY
Change log
+Version 1.7 (minor update)
+'COCONUT' release
+01/05/03
+
+1) In "Special Variable Types" section of "Introduction to Variables and
+ Parameters" chapter:
+ Added note about "$*" and "$@" special variables, and updated "ex17.sh"
+ example to reflect this.
+
+2) In "Manipulating Strings" subsection of "Variables Revisited" chapter:
+ Added "paragraph-space.sh" example.
+
+3) In "Loop Control" section of "Loops and Branches" chapter:
+ Added "continue-n.example" to illustrate use of "continue N" construct.
+ (Thank you, Albert Reiner.)
+
+4) In "Internal Commands" chapter:
+ Added section to "read-redir.sh" example to show setting "$IFS" within a
+ loop. (Thanks, Dim Segebart.)
+ Added Rory Winston's example of "eval" usage.
+
+5) In "List Constructs" chapter:
+ Deleted erroneous comment in "ex65.sh."
+ (Thank you, Francisco de Jesus Orozco Ruiz.)
+
+6) In "File Test" section of "Tests" chapter:
+ Added "broken-link.sh" example.
+
+7) In "Internal Variables" section of "Variables Revisited" chapter:
+ Added comment on $PIPESTATUS.
+
+8) In "RANDOM" section of "Variables Revisited" chapter:
+ Added the 'jipe' techniques for generating random numbers within a
+ specified range.
+ Added "pick-card.sh" example. Thank you once more, jipe.
+
+9) In "Miscellaneous Commands" section of "External Commands" Chapter:
+ Amended discussion of "tee" command.
+
+10) In "System and Administrative Commands" chapter:
+ Expanded "ulimit" discussion to include "fork bomb" scenario.
+
+11) In "Aliases" chapter:
+ Slightly revised "alias.sh" example.
+
+12) In "Bibliography" section and as a footnote in "Debugging" chapter:
+ Added reference to Rocky Bernstein's Bash debugger.
+
+13) Various minor fixups on example scripts.
+
+
+
+
Version 1.6 (minor update)
'POMEGRANATE' release
09/29/02
diff --git a/LDP/guide/docbook/abs-guide/abs-guide.sgml b/LDP/guide/docbook/abs-guide/abs-guide.sgml
index 3364aa0f..82ceac12 100644
--- a/LDP/guide/docbook/abs-guide/abs-guide.sgml
+++ b/LDP/guide/docbook/abs-guide/abs-guide.sgml
@@ -264,6 +264,11 @@ Uncomment line below to generate index.
+
+
+
+
+
@@ -284,8 +289,8 @@ Uncomment line below to generate index.
- 1.6
- 29 September 2002
+ 1.7
+ 05 January 2003
@@ -382,6 +387,14 @@ Uncomment line below to generate index.
more script added.
+
+ 1.7
+ 05 January 2003
+ mc
+ 'COCONUT' release: a couple of bugfixes, more material, one
+ more script.
+
+
@@ -402,7 +415,7 @@ Uncomment line below to generate index.
linkend="bzipref">bzip2-ed tarball
including both the SGML source and
rendered HTML, may be downloaded from
+ url="http://personal.riverusers.com/~thegrendel/abs-guide-1.7.tar.bz2">
the author's home site. See the change
log for a revision history.
@@ -442,7 +455,7 @@ Uncomment line below to generate index.
Why Shell Programming?
- A working knowledge of shell scripting is essential to everyone
+ A working knowledge of shell scripting is essential to anyone
wishing to become reasonably adept 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
@@ -532,7 +545,7 @@ Uncomment line below to generate index.
If any of the above applies, consider a more powerful scripting
- language, perhaps Perl, Tcl, Python, or possibly a high-level
+ 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.
@@ -553,7 +566,7 @@ Uncomment line below to generate index.
is not recommended due to certain inherent problems, as pointed out
in an October, 1993 Usenet
- posting by Tom Christiansen).
+ post by Tom Christiansen).
What follows is a tutorial on shell scripting. It relies
@@ -704,8 +717,8 @@ exit $WHATEVER # Doesn't matter. The script will not exit here.#!/bin/sh, the default Bourne Shell
in most commercial variants of UNIX, makes the script portable to non-Linux machines,
- though you may have to sacrifice a few Bash-specific features
- (the script will conform to the
+ though you may have to sacrifice a few Bash-specific features.
+ The script will, however, conform to the
POSIX
Portable
Operating
@@ -713,36 +726,39 @@ exit $WHATEVER # Doesn't matter. The script will not exit here.Interface, an attempt to
standardize UNIX-like
OSes.
- sh standard).
+ sh standard.
Note that the path given at the sha-bang must
- be correct, otherwise an error message, usually Command not
- found will be the only result of running the script.
+ be correct, otherwise an error message -- usually Command
+ not found -- will be the only result of running the
+ script.
#! 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 #!, since the variable assignment line,
lines=50, uses a shell-specific construct.
- Note that #!/bin/sh invokes the default
+ Note again that #!/bin/sh invokes the default
shell interpreter, which defaults to /bin/bash
on a Linux machine.
- This tutorial encourages a modular approach
+
+ This tutorial encourages a modular approach
to constructing a script. Make note of and collect
boilerplate 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.
+ number of parameters.
- if [ $# -ne Number_of_expected args ]
+ if [ $# -ne Number_of_expected args ]
then
echo "Usage: `basename $0` whatever"
exit $WRONG_ARGS
fi
-
+
+
@@ -755,7 +771,7 @@ fi
script may therefore fail to execute.
or alternatively bash scriptname. (Not
- recommended is using sh <scriptname,
+ recommended is using sh <scriptname>,
since this effectively disables reading from
stdin within the script.) Much more
convenient is to make the script itself directly executable with
@@ -2994,6 +3010,9 @@ arch=$(uname -m)
After $9, the arguments must be enclosed in brackets,
for example, ${10}, ${11}, ${12}.
+ The special variables $* and $@
+ denote all the positional parameters.
+
Positional Parameters&ex17;
@@ -4252,9 +4271,14 @@ home=/home/bozo
+
+ Testing for broken links
+ &brokenlink;
+
+
, ,
, , and illustrate uses of the file test
+ linkend="mailformat"> also illustrate uses of the file test
operators.
@@ -5844,7 +5868,8 @@ echo "Last command argument processed = $last_cmd_arg"
pipe
- Exit status of last executed Exit status of last executed
+ foreground pipe. Interestingly enough,
this does not give the same result as the exit status of the last
@@ -5867,6 +5892,36 @@ echo "Last command argument processed = $last_cmd_arg"
+
+
+
+ The $PIPESTATUS variable
+ may contain an erroneous 0 value
+ in a login shell.
+
+
+
+
+tcsh% bash
+
+bash$ who | grep nobody | sort
+bash$ echo ${PIPESTATUS[*]}
+0
+
+
+
+
+ The above lines contained in a script would produce the expected
+ 0 1 0 output.
+
+
+
+ Thank you, Wayne Pollock for pointing this out and supplying the
+ above example.
+
+
+
+
@@ -6547,7 +6602,8 @@ echo $_ # :expr
-
+
+ stringZ=abcABC123ABCabc
echo ${#stringZ} # 15
@@ -6555,10 +6611,16 @@ echo `expr length $stringZ` # 15
echo `expr "$stringZ" : '.*'` # 15
+
+
+ Inserting a blank line between paragraphs in a text file
+ ¶graphspace;
+
+
Length of Matching Substring at Beginning of String
@@ -7600,10 +7662,37 @@ echo "number = $number" # number = 0
&ex21;
- Just how random is RANDOM? The best way to test this is
+
+ Picking a random card from a deck
+ &pickcard;
+
+
+
+
+
+
+ Jipe points out another set of techniques
+ for generating random numbers within a range.
+
+
+
+ # 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.
+
+
+
+
+
+ Just how random is $RANDOM? The best way to test this is
to write a script that tracks the distribution of
- random numbers generated by RANDOM. Let's roll
- a RANDOM die a few times...
+ random numbers generated by $RANDOM. Let's roll
+ a $RANDOM die a few times...Rolling the die with RANDOM
@@ -8139,6 +8228,11 @@ echo "number = $number" # number = 0
&continuelevels;
+
+ Using continue N in an actual task
+ &continuenex;
+
+
The continue N construct is
difficult to understand and tricky to use in any meaningful
context. It is probably best avoided.
@@ -8860,6 +8954,17 @@ done&rot14;
+ Rory Winston contributed the following instance of how
+ useful eval can be.
+
+
+ Using eval to force variable
+ substitution in a Perl script
+ &evalex;
+
+
+
+
The eval command can be
risky, and normally should be avoided when there
exists a reasonable alternative. An eval
@@ -14495,8 +14600,8 @@ LIMIT_STRING
[UNIX borrows an idea here from the plumbing trade.]This is a redirection operator, but with a difference. Like the
- plumber's tee, it permits siponing
- off the output of a command
+ plumber's tee, it permits siponing
+ offto a file 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.
@@ -17248,16 +17353,45 @@ then
ulimit
- Sets an upper limit on system
- resources. Usually invoked with the
- option, which sets a limit on file size (ulimit
- -f 1000 limits files to 1 meg maximum). The
- option limits the coredump size
- (ulimit -c 0 eliminates coredumps).
+
+ Sets an upper limit on use
+ of system resources. Usually invoked with the
+ option, which sets a limit on file size
+ (ulimit -f 1000 limits files to 1 meg
+ maximum). The option limits the coredump
+ size (ulimit -c 0 eliminates coredumps).
Normally, the value of ulimit
would be set in /etc/profile
and/or ~/.bash_profile (see ).
+
+
+
+ Judicious use of ulimit can
+ protect a system against the dreaded fork
+ bomb.
+
+
+ #!/bin/bash
+
+while 1 # Endless loop.
+do
+ $0 & # This script invokes itself . . .
+ #+ forks an infinite number of times . . .
+ #+ until the system freezes up because all resources exhausted.
+done # This is the notorious sorcerer's appentice scenario.
+
+exit 0 # Will not exit here, because this script will never terminate.
+
+
+ A ulimit -Hu XX (where
+ XX is the user process limit) in
+ /etc/profile would abort
+ this script when it exceeds the preset limit.
+
+
+
+
@@ -20256,9 +20390,10 @@ false && ( true || echo false ) # (nothing echoed)
# Thanks, S.C.
- See for an illustration of using
- an and / or list to test variables.
-
+ See and for illustrations of using an and
+ / or list to test variables.
+
@@ -20857,9 +20992,16 @@ ln -s /dev/null ~/.netscape/cookies
DebuggingThe Bash shell contains no debugger, nor even any
- debugging-specific commands or constructs. Syntax errors or
- outright typos in the script generate cryptic error messages that
- are often of no help in debugging a non-functional script.
+ debugging-specific commands or constructs.
+
+ Rocky Bernstein's
+ Bash debugger
+ partially makes up for this lack.
+
+ Syntax errors or outright typos in the script generate cryptic
+ error messages that are often of no help in debugging a
+ non-functional script.
A buggy script
@@ -22946,8 +23088,9 @@ fi
were Gabor Kiss, Leopold Toetsch, Peter Tillier, Marcus Berglof,
Tony Richardson, Nick Drage (script ideas!), Rich Bartell, Jess
Thrysoee, Adam Lazur, Bram Moolenaar, Baris Cicek, Greg Keraunen,
- Keith Matthews, Sandro Magi, and David Lawyer (himself an author
- of 4 HOWTOs).
+ Keith Matthews, Sandro Magi, Albert Reiner, Dim Segebart, Rory
+ Winston, Lee Bigelow, Wayne Pollock, jipe, and
+ David Lawyer (himself an author of 4 HOWTOs).
My gratitude to Chet
Ramey and Brian Fox for writing Bash,
@@ -23499,6 +23642,15 @@ fi
Hohensee has written the
osimpa i386 assembler entirely as Bash scripts.
+
+
+
+
+
+ Rocky Bernstein is in the process of developing a
+ full-fledged debugger for
+ Bash.---
diff --git a/LDP/guide/docbook/abs-guide/alias.sh b/LDP/guide/docbook/abs-guide/alias.sh
index c0fa88c5..56008764 100644
--- a/LDP/guide/docbook/abs-guide/alias.sh
+++ b/LDP/guide/docbook/abs-guide/alias.sh
@@ -55,20 +55,19 @@ do
alias rrr="ls -l"
echo "Trying aliased \"rrr\" within \"while\" loop:"
rrr /usr/X11R6/bin/mk* #* Alias will not expand here either.
+ # alias.sh: line 57: rrr: command not found
let count+=1
done
echo; echo
-alias xyz="cat $1" # Try a positional parameter in an alias.
-xyz # Assumes you invoke the script
- #+ with a filename as a parameter.
+alias xyz='cat $0' # Script lists itself.
+ # Note strong quotes.
+xyz
# This seems to work,
#+ although the Bash documentation suggests that it shouldn't.
#
# However, as Steve Jacobson points out,
-#+ the "$1" parameter expands immediately upon declaration of the alias,
-#+ so, in the strictest sense, this is not an example
-#+ of parameterizing an alias.
+#+ the "$0" parameter expands immediately upon declaration of the alias.
exit 0
diff --git a/LDP/guide/docbook/abs-guide/escaped.sh b/LDP/guide/docbook/abs-guide/escaped.sh
index 6aa08d39..f8c764f0 100644
--- a/LDP/guide/docbook/abs-guide/escaped.sh
+++ b/LDP/guide/docbook/abs-guide/escaped.sh
@@ -26,8 +26,9 @@ echo "QUOTATION MARKS"
echo $'\t \042 \t' # Quote (") framed by tabs.
# It also works with hexadecimal values, in an $'\xhhh' construct.
-echo $'\t \x022 \t' # Quote (") framed by tabs.
+echo $'\t \x22 \t' # Quote (") framed by tabs.
# Thank you, Greg Keraunen, for pointing this out.
+# Earlier Bash versions allowed '\x022'.
echo "==============="
echo
diff --git a/LDP/guide/docbook/abs-guide/ex17.sh b/LDP/guide/docbook/abs-guide/ex17.sh
index e9974b01..157e7971 100644
--- a/LDP/guide/docbook/abs-guide/ex17.sh
+++ b/LDP/guide/docbook/abs-guide/ex17.sh
@@ -36,8 +36,12 @@ then
echo "Parameter #10 is ${10}"
fi
+echo "-----------------------------------"
+echo "All the command-line parameters are: "$*""
+
if [ $# -lt "$MINPARAMS" ]
then
+ echo
echo "Give me at least $MINPARAMS command-line arguments!"
fi
diff --git a/LDP/guide/docbook/abs-guide/ex65.sh b/LDP/guide/docbook/abs-guide/ex65.sh
index 3447a036..f9c26b30 100644
--- a/LDP/guide/docbook/abs-guide/ex65.sh
+++ b/LDP/guide/docbook/abs-guide/ex65.sh
@@ -21,7 +21,6 @@ Cowardly refusing to delete a nonexistent file."
[ ! -f "$file" ] || (rm -f $file; echo "File \"$file\" deleted.")
# OR LIST, to delete file if present.
-# ( command1 ; command2 ) is, in effect, an AND LIST variant.
# Note logic inversion above.
# AND LIST executes on true, OR LIST on false.
diff --git a/LDP/guide/docbook/abs-guide/file-comparison.sh b/LDP/guide/docbook/abs-guide/file-comparison.sh
index 5b8dfb3d..590bff02 100644
--- a/LDP/guide/docbook/abs-guide/file-comparison.sh
+++ b/LDP/guide/docbook/abs-guide/file-comparison.sh
@@ -17,6 +17,9 @@ then
fi
cmp $1 $2 &> /dev/null # /dev/null buries the output of the "cmp" command.
+# cmp -s $1 $2 has same result ("-s" silent flag to "cmp")
+# Thank you Anders Gustavsson for pointing this out.
+#
# Also works with 'diff', i.e., diff $1 $2 &> /dev/null
if [ $? -eq 0 ] # Test exit status of "cmp" command.
diff --git a/LDP/guide/docbook/abs-guide/read-redir.sh b/LDP/guide/docbook/abs-guide/read-redir.sh
index e66abedd..d3009a84 100644
--- a/LDP/guide/docbook/abs-guide/read-redir.sh
+++ b/LDP/guide/docbook/abs-guide/read-redir.sh
@@ -37,4 +37,21 @@ done </etc/passwd # I/O redirection.
IFS=$OIFS # Restore originial $IFS.
# This code snippet also by Heiner Steven.
+
+
+# Setting the $IFS variable within the loop itself
+#+ eliminates the need for storing the original $IFS
+#+ in a temporary variable.
+# Thanks, Dim Segebart, for pointing this out.
+echo "------------------------------------------------"
+echo "List of all users:"
+
+while IFS=: read name passwd uid gid fullname ignore
+do
+ echo "$name ($fullname)"
+done </etc/passwd # I/O redirection.
+
+echo
+echo "\$IFS still $IFS"
+
exit 0