diff --git a/LDP/guide/docbook/abs-guide/Change.log b/LDP/guide/docbook/abs-guide/Change.log
index 2a4065aa..10376e4e 100644
--- a/LDP/guide/docbook/abs-guide/Change.log
+++ b/LDP/guide/docbook/abs-guide/Change.log
@@ -7,19 +7,152 @@
==================================================================
- Current version = 5.6
- Dated 01/26/09
+ Current version = 6.0.05
+ Dated 03/24/09
http://bash.neuralshortcircuit.com/abs-guide-latest.tar.bz2
http://bash.neuralshortcircuit.com/abs-guide.pdf
--------------------------------------------------------------------
- News: Added Knight's Tour script (ktour.sh),
- Magic Square script (msquare.sh).
- --------------------------------------------------------------------
- Remarks: Gradually adding in-line definitions for technical terms,
- usually as sidebars, less often as footnotes.
+ News: Major update, version 6.0.
+ Coverage of version 4 of Bash.
====================================================================
+Intermediate release
+Working toward Version 6.1, Buffaloberry release
+
+1) In "Internal Commands and Builtins" chapter
+ At "eval" entry, reworded intro and added material to first example.
+
+2) In "External Commands" chapter:
+ In "Math Commands" section:
+ At "dc" entry, added two short usage example, including a
+ somewhat cryptic one (Golden Ratio calculation).
+
+3) In "Internal Variables" section of "Variables Revisited" chapter:
+ At "$DIRSTACK" entry, added footnote defining "stack."
+
+4) In "Bash, versions 2, 3, and 4" chapter:
+ In "Bash, version 4" section,
+ Corrected a typo in Substring Extraction entry example script.
+
+5) In "Bibliography" section:
+ Added entry for Wikipedia article on "dc."
+
+
+
+
+
+Version 6.0, Thimbleberry release
+March 23, 2009
+
+1) Changed the title of Chapter 1.
+
+2) Updated "copy-cd.sh" and "ex40.sh" examples
+ to reflect changes in cdrtools.
+
+3) In "Special Characters" chapter:
+ Added another instance in the "brace expansion" example.
+
+4) In "Testing and Branching" section of "Loops and Branches" chapter:
+ Clarified outline of "case" construct.
+
+5) In "Internal Commands and Builtins" chapter:
+ At "eval" entry, added "arr-choice.sh" example script.
+ (Thank you, Antonio Macchi!)
+ At "read" entry, added "-u" option.
+
+6) In "Internal Variables" section of "Variables Revisited" chapter:
+ Added $BASHPID variable (new to Bash 4+).
+ At "$$" entry, noted that within a subshell, PID of script returned
+ by $$.
+
+7) In "Arrays" chapter:
+ Added material to "array-function.sh" example script.
+
+8) In "Variables Revisited" chapter:
+ In "Indirect References" section:
+ Fixed comment in "ind-ref.sh" example, thanks to Jakob Bohm.
+
+9) In "External Commands" chapter:
+ In "File and Archiving Commands" section:
+ Added "pax" entry.
+
+10) In "I/O Redirection" chapter:
+ Added a couple of new instances on stderr redirection.
+ Added comments on a couple of new operators added in ver. 4 of Bash
+ that are still not functional.
+
+11) In "Bash, versions 2, 3, and 4" chapter (new title!):
+ In Version 3 section, more on quoting "=~" operator.
+ Added instances in "brace expansion" example.
+
+ Added a section for version 4 of Bash.
+ Added "fetch_address.sh" and "fetch_address-2.sh" examples
+ to illustrate associative arrays.
+ Added "cas4.sh" example to illustrate enhancements to case construct.
+ Added discussion of the new "coproc" command, with illustrative
+ examples.
+ Added discussion of the new "mapfile" command, with an illustrative
+ example.
+ Briefly mentioned a couple of the changes to "read" options.
+ Listed the new -l and -c options to "declare" builtin,
+ with a short illustrated inline script.
+ Listed new upper/lowercase operators for parameter substitution,
+ with example.
+ Listed the new "brace expansion" options.
+ Discussed change in the treatment of positional parameters
+ in substring extraction.
+ Discussed the new ** globbing operator and "globstar" shell option.
+ Discussed the new "command_not_found_handle ()" error-handling
+ function, with in-line example.
+ Added an "editorial" sidebar. It is certain to generate controversy.
+
+12) In "System Resources" subsection of "System and Administrative
+ At "ulimit" entry, added footnote about -f, -c behavior in POSIX
+ mode and newly-added options (ver. 4+ of Bash).
+
+13) In "Process Substitution" chapter:
+ Added "wr-ps.bash" while-read loop example.
+ (Thank you, Tomas Pospisek!)
+
+14) In "Gotchas" chapter:
+ Samuli Kaipiainen supplied a corrected explanation for piping-to-grep
+ misbehavior.
+
+15) In the "Portability Issues" section of the "Miscellany" chapter:
+ Added entries to list of features in Bash missing in traditional "sh."
+
+16) In "Options" chapter:
+ Added entries for "globstar" and "checkjobs" in the table.
+
+17) In "Subshells" chapter:
+ Added a few comments and a short in-line example.
+
+18) In "Contributed Scripts" appendix:
+ Added "fifteen.sh" (Fifteen Puzzle) example script.
+ (Thank you, Antonio Macchi!)
+ Added "hanoi2.bash" -- graphic version of "hanoi.bash."
+ Added "hanoi2a.bash" -- alternate graphic version of "hanoi.bash."
+ Had to remove "obj-oriented.sh" example because it only works
+ with obsolete versions of Bash.
+ Removed "ftpget.sh" script.
+
+19) In "Download and Mirror Sites" appendix:
+ Fixed a typo in the ABS Guide download URL.
+
+20) In "Bibliography" section:
+ Added Shell Script Games entry.
+ Added Bash Hackers Wiki entry.
+ Added mirror site for the official Bash FAQ.
+ Added Greg's WIKI: Bash FAQ entry.
+ Added joyent site.
+
+21) Updated the Index with references to new material.
+
+22) Numberous syntactical and stylistic fixes.
+
+
+
Version 5.6, Worcesterberry release
01/26/09
diff --git a/LDP/guide/docbook/abs-guide/INDEX00.sgml b/LDP/guide/docbook/abs-guide/INDEX00.sgml
index d6bbb9fd..6bbf44c0 100644
--- a/LDP/guide/docbook/abs-guide/INDEX00.sgml
+++ b/LDP/guide/docbook/abs-guide/INDEX00.sgml
@@ -11,9 +11,23 @@
^ (caret)
- Beginning-of-line, in a Regular Expression
+
+
+
+ Beginning-of-line,
+ in a Regular Expression
+
+
+
+ ^
+ ^^
+ Uppercase
+ conversion in parameter
+ substitution
+
+
+
~ Tilde
@@ -233,9 +247,8 @@
command;;
Double-semicolon, terminator in a
- case option
+ case option
- Required when ...do
keyword is on the first line of
@@ -245,6 +258,11 @@
code block
+ ;;&;&
+ Terminators in
+ a case option (version 4+ of Bash).
+
:
@@ -342,7 +360,19 @@
quoting,
- Comma operator
+
+
+ Comma operator
+
+
+ ,
+ ,,
+ Lowercase
+ conversion in parameter
+ substitution
+
+
+
@@ -618,6 +648,12 @@
arithmetic operator
+
+ **
+ Extended globbing
+ file-match operator
+
+
@@ -769,6 +805,8 @@
Arrays
+ Associative arrays
+ Bracket notation
Concatenating,
@@ -881,6 +919,8 @@
Version 2
Version 3
+
+ Version 4
@@ -931,6 +971,10 @@
Extended,
{a..z}
+ With increment and
+ zero-padding (new feature in Bash, version
+ 4)
@@ -1029,6 +1073,10 @@
Command-line options
+ command_not_found_handle ()
+ builtin error-handling function
+ (version 4+ of Bash)
+
Command substitution
@@ -1100,6 +1148,7 @@
+ Coprocessescron, scheduling
daemonC-style syntax
@@ -1167,8 +1216,11 @@
declare builtin
- options
+
+ options
+ case-modification
+ options (version 4+ of Bash)
+ Default parameters
@@ -1285,6 +1337,9 @@
referencesRisk of
using
+ Using
+ eval to select among
+ variablesEvaluation of
@@ -1496,6 +1551,8 @@
linkend="cryptoquote">Crypto-QuotesDealing a deck of cards
+ Fifteen PuzzleHorse racePodcastingPoemTowers of Hanoi
+ linkend="hanoi">Towers of Hanoi
+ Graphic
+ version
+ Alternate graphic
+ version
+
getopt,
@@ -1549,6 +1611,9 @@
dot files
+ Golden Ratio
+ (Phi)
+
-ge ,
greater-than or equal
integer comparison test
@@ -1608,6 +1673,8 @@
Here
strings
+ Calculating the Golden
+ RatioPrepending textUsing
read
@@ -1911,6 +1978,8 @@
+ mapfile builtin,
+ loads an array with a text fileMath commandsMeta-meaning
@@ -2019,6 +2088,11 @@
parameter
+
+ Case modification
+ (version 4+ of
+ Bash).
+
Script
exampleTable
@@ -2161,7 +2235,9 @@
echo
to a loopecho
- to read
+ to read (however, this problem
+ can be circumvented)
+
tail
to grep
@@ -2180,6 +2256,9 @@
Variables in a
subshell, scope
limited
+ Subshell in while-read
+ loopWhitespace,
misuse of
@@ -2297,6 +2376,10 @@
command
Template
+ while-read loop
+ without a
+ subshellPrompt
@@ -2427,6 +2510,8 @@
construct
+ readline library
+
Recursion
Special characters
- Stack, emulating a push-down, example
- script
+
+ Stack
+
+ Definition
+ Emulating a push-down stack,
+ example script
+
+
Standard Deviation, example scriptStartup files, Bash
@@ -3089,7 +3180,12 @@
Testing a variable
to see if it contains only digitsTracking script usage
+ linkend="trackingscr">Tracking script
+ usage
+ while-read loop
+ without a
+ subshellWidgets, invoking from a
script
@@ -3288,9 +3384,14 @@
conditions
Omitting
test brackets
-
- while read
- construct
+
+
+ while read
+ construct
+
+ Avoiding a
+ subshell
+ Whitespace,
diff --git a/LDP/guide/docbook/abs-guide/abs-guide.sgml b/LDP/guide/docbook/abs-guide/abs-guide.sgml
index 3f8d2ad8..5fd693c5 100644
--- a/LDP/guide/docbook/abs-guide/abs-guide.sgml
+++ b/LDP/guide/docbook/abs-guide/abs-guide.sgml
@@ -97,7 +97,6 @@
-
@@ -199,7 +198,6 @@
-
@@ -298,6 +296,8 @@
+
+
@@ -334,6 +334,7 @@
+
@@ -354,6 +355,10 @@
+
+
+
+
@@ -361,6 +366,7 @@
+
@@ -384,21 +390,14 @@
- 5.6
- 26 January 2009
+ 6.0.05
+ 24 March 2009978-1-4357-5219-1
-
- 5.4
- 21 July 2008
- mc
- 'ANGLEBERRY' release: Major Update.
-
-
5.523 Nov 2008
@@ -413,6 +412,13 @@
'WORCESTERBERRY' release: Minor Update.
+
+ 6.0
+ 23 Mar 2009
+ mc
+ 'THIMBLEBERRY' release: Minor Update.
+
+
@@ -472,7 +478,7 @@
- Why Shell Programming?
+ Shell Programming!No programming language is perfect. There is not even a single
@@ -1158,6 +1164,35 @@ esac
+
+ ;;&
+ ;&
+
+ ;;&
+
+
+ special character
+ ;;&
+
+
+ ;&
+ case statement
+
+
+ ;&
+
+
+ Terminators
+ in a case option (version 4+ of Bash).
+
+
+
+
+
+
+
..
@@ -1336,8 +1371,8 @@ esac
- The comma operator can also
- concatenate strings.
+ The comma
+ operator can also concatenate strings.
for file in /{,usr/}bin/*calc
# ^ Find all executable files ending in "calc"
#+ in /bin and /usr/bin directories.
@@ -1358,8 +1393,22 @@ done
+
+
+ ,
+ ,
+
+ Lowercase
+ conversion in parameter substitution
+ (added in version 4 of Bash)
+
+
+
+
+
\escape [backslash]
@@ -1507,8 +1556,8 @@ fi
target file (: >> target_file).
If the file did not previously exist, creates it.
- This applies to regular files, not pipes,
- symlinks, and certain special files.
+ This applies to regular files,
+ not pipes, symlinks, and certain special files.May be used to begin a comment line, although this is not
@@ -1645,9 +1694,10 @@ fi
- A double asterisk, **, is the exponentiation
- operator.
+ ** A double asterisk can represent the
+ exponentiation
+ operator or extended
+ file-match globbing.
@@ -1950,14 +2000,18 @@ echo "a = $a" # a = 123
{xxx,yyy,zzz,...}Brace expansion
- cat {file1,file2,file3} > combined_file
+
+echo \"{These,words,are,quoted}\" # " prefix and suffix
+# "These" "words" "are" "quoted"
+
+
+cat {file1,file2,file3} > combined_file
# Concatenates the files file1, file2, and file3 into combined_file.
-
cp file22.{txt,backup}
-# Copies "file22.txt" to "file22.backup"
-
+# Copies "file22.txt" to "file22.backup"
+
A command may act upon a comma-separated list of file specs within
braces.
@@ -3060,6 +3114,10 @@ echo $z # 2beginning of line
+
+ uppercase modification
+ parameter substitution
+ beginning-of-line
@@ -3071,6 +3129,18 @@ echo $z # 2
+
+ ^
+ ^^
+
+ Uppercase
+ conversion in parameter substitution
+ (added in version 4 of Bash)
+
+
+
+
Control Characters
@@ -6593,6 +6663,7 @@ echo "t2 = $t2 a = $a" # t2 = 5 a = 9
+
$BASH_SUBSHELL
@@ -6610,6 +6681,54 @@ echo "t2 = $t2 a = $a" # t2 = 5 a = 9
+
+
+ $BASHPID
+
+ $BASHPID
+
+
+ variable
+ process ID
+
+ Process ID
+ of the current instance of Bash. This is not the same as the
+ $$ variable, but it often
+ gives the same result.
+
+
+bash4$ echo $$
+11015
+
+
+bash4$ echo $BASHPID
+11015
+
+
+bash4$ ps ax | grep bash4
+11015 pts/2 R 0:00 bash4
+
+
+ But ...
+
+#!/bin/bash4
+
+echo "\$\$ outside of subshell = $$" # 9602
+echo "\$BASH_SUBSHELL outside of subshell = $BASH_SUBSHELL" # 0
+echo "\$BASHPID outside of subshell = $BASHPID" # 9602
+
+echo
+
+( echo "\$\$ inside of subshell = $$" # 9602
+ echo "\$BASH_SUBSHELL inside of subshell = $BASH_SUBSHELL" # 1
+ echo "\$BASHPID inside of subshell = $BASHPID" ) # 9603
+ # Note that $$ returns PID of parent process.
+
+
+
+
+
$BASH_VERSINFO[n]
@@ -6691,6 +6810,18 @@ done
stackThe top value in the directory stack
+
+
+ A stack register
+ is a set of consecutive memory locations, such that
+ the values stored (pushed)
+ are retrieved (popped)
+ in reverse order. The last
+ value stored is the first retrieved. This is
+ sometimes called a LIFO
+ (last-in-first-out) or
+ pushdown stack.
+
(affected by pushd and popd)This builtin
variable corresponds to the dirs
@@ -8051,14 +8182,21 @@ echo $_ # :
PIDof script
- Process ID of the script itself. The
- $$ variable often finds use
- in scripts to construct unique
- temp file names (see , , , and ). This is usually simpler than
- invoking mktemp.
-
+ Process ID (PID) of
+ the script itself.
+
+ Within a script, inside a subshell,
+ $$ returns
+ the PID of the script, not the
+ subshell.
+
+ The $$ variable often
+ finds use in scripts to construct unique
+ temp file names (see , , and ).
+ This is usually simpler than invoking mktemp.
+
@@ -8281,6 +8419,7 @@ echo ${stringZ: -4} # Cabc
&randstring;
+ If the $string parameter is
* or
@, then this extracts a maximum
@@ -10400,24 +10539,29 @@ done
"$condition2" )command ;;
- esac
+ esac
- Quoting the variables is not mandatory, since
- word splitting does not take place.
+ Quoting the variables is not mandatory,
+ since word splitting does not take place.Each test line
ends with a right paren ).
- Each condition block ends with a double
- semicolon ;;.
+ Each condition block ends
+ with a double semicolon
+ ;;.
- The entire case block terminates with an
- esac (case spelled
- backwards).
+ If a condition tests
+ true, then the associated
+ commands execute and the case
+ block terminates.
+ The entire case
+ block ends with an esac
+ (case spelled backwards).
@@ -11126,6 +11270,7 @@ let "z += 3" # Quotes permit the use of spaces in variable assignment.
commcommandcompress
+ coproccpcpiocron
@@ -11264,6 +11409,7 @@ let "z += 3" # Quotes permit the use of spaces in variable assignment.
makeMAKEDEVman
+ mapfilemcookiemd5summerge
@@ -11301,6 +11447,7 @@ let "z += 3" # Quotes permit the use of spaces in variable assignment.
patch
(Related topic: diff)pathchk
+ paxpgreppidofping
@@ -11840,6 +11987,10 @@ echo; echo "Keypress was "\"$keypress\""."
permits timed input (see and ).
+ The option
+ takes the file descriptor
+ of the target file.
+
The read command may also
read its variable value from a file
@@ -12018,10 +12169,12 @@ while read f; do
bookmark
- 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.
+ 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.pushd
dir-name pushes the path
@@ -12107,14 +12260,28 @@ while read f; do
eval arg1 [arg2] ... [argN]Combines the arguments in an expression or list of
- expressions and evaluates them. Any
- variables contained within the expression are expanded. The
- result translates into a command. This can be useful for
- code generation from the command-line or within a script.
-
+ expressions and evaluates them.
+ Any variables within the expression are expanded. The
+ net result is to convert a string into a
+ command.
+
+ The eval command can be used for
+ code generation from the command-line or within a script.
+
+bash$ command_string=xterm
+bash$ eval $command_string
+Filesystem 1K-blocks Used Available Use% Mounted on
+ /dev/sda5 1904920 590204 1217952 33% /
+ /dev/sda9 5409672 892396 4517276 17% /home
+ /dev/sda1 18431244 13244376 5186868 72% /media/hd
+ /dev/sda7 10142384 7812496 1814676 82% /usr
+ /dev/sda8 1138428 258964 821632 24% /var
+
+
+
bash$ process=xtermbash$ show_process="eval ps ax | grep $process"bash$ $show_process
@@ -12147,6 +12314,13 @@ eval eval echo $a # d
&ex43;
+
+
+ Using eval to select
+ among variables
+ &arrchoice;
+
+
Echoing the
command-line parameters
@@ -12919,8 +13093,9 @@ done
variable$PATH
- Record the path name of specified commands -- in the
- shell hash table
+ Records the path
+ name of specified commands -- in the shell hash
+ table
@@ -12932,19 +13107,19 @@ done
algorithms (methods, or
recipes).
- An advantage of hashing is that it
- is fast. A disadvantage is that collisions --
- where a single key maps to more than one data item -- are
- possible.
+ An advantage of hashing is that
+ it is fast. A disadvantage is that
+ collisions -- where a single key
+ maps to more than one data item -- are possible.For examples of hashing see and
.
- -- so the shell or script will not need to search
- the $PATH on subsequent calls to those
+ -- so the shell or script will not need to search the
+ $PATH on subsequent calls to those
commands. When hash is called with no
- arguments, it simply lists the commands that have been hashed.
+ arguments, it simply lists the commands that have been hashed.
The option resets the hash table.
@@ -12963,9 +13138,10 @@ done
The bind builtin displays or modifies
readline
- The readline library
- is what Bash uses for reading input in an interactive
- shell.
+ The
+ readline library is what
+ Bash uses for reading input in an
+ interactive shell.
key bindings.
@@ -12984,7 +13160,9 @@ done
Gets a short usage summary of a shell builtin. This is
the counterpart to whatis,
- but for builtins.
+ but for builtins. The display of help
+ information got a much-needed update in the version 4 release of Bash.bash$ help exit
@@ -16516,6 +16694,44 @@ function write_utf8_string {
+
+ pax
+
+ pax
+
+
+ command
+ archive
+
+
+
+ The pax
+ portable archive
+ exchange toolkit
+ facilitates periodic file backups and is designed
+ to be cross-compatible between various flavors of UNIX.
+ It was ported from BSD to Linux.
+
+
+ pax -wf daily_backup.pax ~/linux-server/files
+# Creates a tar archive of all files in the target directory.
+# Note that the options to pax must be in the correct order --
+#+ pax -fw has an entirely different effect.
+
+pax -f daily_backup.pax
+# Lists the files in the archive.
+
+pax -rf daily_backup.pax ~/bsd-server/files
+# Restores the backed-up files from the Linux machine
+#+ onto a BSD one.
+
+
+ Note that pax handles many of
+ the standard archiving and compression commands.
+
+
+
+
@@ -18215,8 +18431,8 @@ fiUtility and protocol for uploading / downloading
files to or from a remote host. An ftp session can be automated
- in a script (see , , and ).
+ in a script (see and ).
@@ -18979,13 +19195,21 @@ LIMIT_STRING
The dc (desk
- calculator) utility is stack-oriented
+ calculator) utility is stack-oriented
and uses RPN (Reverse Polish Notation). Like
bc, it has much of the power of a
programming language.
- Most persons avoid dc, since it
- requires non-intuitive input. Yet, it has its uses.
+
+ echo "7 8 * p" | dc # 56
+# Pushes 7, then 8 onto the stack,
+#+ multiplies ("*" operator), then prints the result ("p" operator).
+
+
+ Most persons avoid dc, because
+ of its non-intuitive input and rather cryptic
+ operators. Yet, it has its uses.Converting a decimal number to hexadecimal
@@ -19004,6 +19228,18 @@ LIMIT_STRING
+
+ dc <<< 10k5v1+2/p # 1.6180339887
+# ^^^ Feed operations to dc using a Here String.
+# ^^^ Pushes 10 and sets that as the precision (10k).
+# ^^ Pushes 5 and takes its square root (5v, v = square root).
+# ^^ Pushes 1 and adds it to the running total (1+).
+# ^^ Pushes 2 and divides the running total by that (2/).
+# ^ Pops and prints the result (p)
+# The result is 1.6180339887 ...
+# ... which happens to be the Pythagorean Golden Ratio, to 10 places.
+
+
Factoring&factr;
@@ -23124,12 +23360,22 @@ then #+ Prevent other programs & scripts
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
+ maximum).
+ As of the version
+ 4 update of Bash, the
+ and options take a block size
+ of 512 when in POSIX
+ mode. Additionally, there are two new options:
+ for socket buffer size, and
+ for the limit on the number of
+ threads.
+ 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 ).
+ Normally, the value of ulimit
+ would be set in /etc/profile
+ and/or ~/.bash_profile (see ).
@@ -24335,11 +24581,12 @@ then # POSIX char class
Bash does carry out filename
expansion
- Filename expansion means
- expanding filename patterns or templates containing special
- characters. For example, example.??? might
- expand to example.001 and/or
- example.txt.
+ Filename expansion
+ means expanding filename patterns or templates
+ containing special characters. For example,
+ example.??? might expand
+ to example.001 and/or
+ example.txt.
-- a process known as globbing -- but
this does not use the standard RE set.
@@ -24834,7 +25081,9 @@ echo "Seventh word in String is: ${Words[6]}" # (null)
Exercise: Find other uses for here
- strings.
+ strings, such as, for example, feeding input to
+ dc.
@@ -24870,7 +25119,7 @@ echo "Seventh word in String is: ${Words[6]}" # (null)
to keep track of it. Consider it a simplified
type of file pointer. It is analogous
to a file handle in
- C.
+ C.
The file descriptors for stdin,
stdout, and stderr are
@@ -24933,6 +25182,8 @@ echo "Seventh word in String is: ${Words[6]}" # (null)
#+ stdout and stderr to file "filename" --
#+ fails with the error message,
#+ syntax error near unexpected token `>'.
+ # The &>> operator is supposed to be functional in Bash 4,
+ #+ but as of version 4.0 still is not.
M>N
# "M" is a file descriptor, which defaults to 1, if not explicitly set.
@@ -24972,6 +25223,14 @@ echo "Seventh word in String is: ${Words[6]}" # (null)
2>&1
# Redirects stderr to stdout.
# Error messages get sent to same place as standard output.
+ >>filename 2>&1
+ bad_command >>filename 2>&1
+ # Appends both stdout and stderr to the file "filename" ...
+ 2>&1 | [command(s)]
+ bad_command 2>&1 | awk '{print $5}' # found
+ # Sends stderr through a pipe.
+ # |& was added to Bash 4 as an abbreviation for 2>&
+ #+ but as of version 4.0 this still does not work.
i>&j
# Redirects file descriptor i to j.
@@ -25081,8 +25340,9 @@ ls -yz 2>&1 >> command.log
- Child processes inherit open file descriptors. This is why pipes
- work. To prevent an fd from being inherited, close it.
+
+ Child processes inherit open file descriptors. This is
+ why pipes work. To prevent an fd from being inherited, close it.
# Redirecting only stderr to a pipe.
exec 3>&1 # Save current "value" of stdout.
@@ -25358,11 +25618,10 @@ but is shown here for illustrative purposes.An external command invoked with an exec does not
(usually) fork off a subprocess / subshell.
- whereas a Bash builtin does not. For this reason,
- builtins execute more quickly than their external command
- equivalents.
-
+ whereas a Bash builtin
+ does not. For this reason, builtins execute more quickly
+ and use fewer system resources than their external command
+ equivalents.
@@ -25391,7 +25650,8 @@ but is shown here for illustrative purposes.
Variable scope in a subshell&subshell;
- See also .
+ See also $BASHPID and
+ .
@@ -25518,10 +25778,17 @@ fi
operator, as in ls -al | (command).
- A command block between curly
- braces does not launch
- a subshell.
- { command1; command2; command3; . . . commandN; }
+
+ A code block between curly brackets does
+ not launch a subshell.
+ { command1; command2; command3; . . . commandN; }
+ var1=23
+echo "$var1" # 23
+
+{ var1=76; }
+echo "$var1" # 76
+
@@ -25738,6 +26005,15 @@ exec 3>&-
# Thanks, Stéphane Chazelas
+ Here is a method of circumventing the
+ problem of an echo
+ piped to a while-read loop running
+ in a subshell.
+
+
+ Code block redirection without forking
+ &wrps;
+ A reader sent in the following interesting example of process
substitution.
@@ -26528,6 +26804,7 @@ exit 0 # This script will not exit normally.
&hanoi;
+
@@ -26994,7 +27271,7 @@ echo $element_count # 8
--Arrays permit deploying old familiar algorithms as shell scripts.
- Whether this is necessarily a good idea is left to the reader to
+ Whether this is necessarily a good idea is left for the reader to
decide.
@@ -28113,6 +28390,20 @@ trap 'echo "Control-C disabled."' 2
+
+
+ brace expansion
+ Enable
+ brace
+ expansion (default setting =
+ on)
+
+
+
+ brace expansion
+ Disable
+ brace expansion
+ noclobber
@@ -28141,6 +28432,16 @@ trap 'echo "Control-C disabled."' 2
(none)Read commands from ...
+
+
+
+ Informs user of any open jobs upon shell exit.
+ Introduced in version 4
+ of Bash, and still experimental.
+ Usage: shopt -s checkjobs
+ (Caution: may hang!)
+ errexit
@@ -28156,6 +28457,16 @@ trap 'echo "Control-C disabled."' 2
noglobFilename expansion (globbing) disabled
+
+
+ globbing
+ star-match
+ Enables the ** globbing operator
+ (version 4+ of Bash).
+ Usage: shopt -s globstar
+ interactive
@@ -28725,11 +29036,14 @@ find $HOME -type f -atime +30 -size 100k | {
- A related problem occurs when trying to write the
+ A lookalike problem occurs when trying to write the
stdout of a tail -f
piped to grep.
tail -f /var/log/messages | grep "$ERROR_MSG" >> error.log
-# The "error.log" file will not have anything written to it.
+# The "error.log" file will not have anything written to it.
+# As Samuli Kaipiainen points out, this results from grep
+#+ buffering its output.
+# The fix is to add the "--line-buffered" parameter to grep.
@@ -30534,6 +30848,15 @@ echo "User entered: "$answer""
$( ) notation
+
+ Brace expansion
+
+
+
+ Certain array operations,
+ and associative arrays
+
+
The double brackets
extended test construct
@@ -30562,6 +30885,10 @@ echo "User entered: "$answer""
Bash-specific builtins
+
+ Coprocesses
+
+
@@ -30597,7 +30924,7 @@ echo "User entered: "$answer""
- Bash, versions 2 and 3
+ Bash, versions 2, 3, and 4Bash, version 2
@@ -30606,22 +30933,17 @@ echo "User entered: "$answer""
The current version of Bash, the one
- you have running on your machine, is most likely version 2.xx.yy
- or 3.xx.yy.
+ you have running on your machine, is most likely version 2.xx.yy,
+ 3.xx.yy, or 4.xx.yy.
bash$ echo $BASH_VERSION3.2.25(1)-releaseThe version 2 update of the classic Bash scripting language
- added array variables,
-
- Chet Ramey has promised associative arrays
- (a nifty Perl feature) in a future Bash release. As of version
- 3.2, this has not yet happened.
-
- string and parameter expansion, and a better method
- of indirect variable references, among other features.
+ added array variables, string and parameter expansion, and
+ a better method of indirect variable references, among other
+ features.
String expansion
@@ -30685,8 +31007,10 @@ echo
# Or just . . .
echo {a..z} # a b c d e f g h i j k l m n o p q r s t u v w x y z
+echo {e..m} # e f g h i j k l m
echo {z..a} # z y x w v u t s r q p o n m l k j i h g f e d c b a
# Works backwards, too.
+echo {25..30} # 25 26 27 28 29 30
echo {3..-2} # 3 2 1 0 -1 -2
echo {X..d} # X Y Z [ ] ^ _ ` a b c d
# Shows (some of) the ASCII characters between Z and a,
@@ -30695,8 +31019,24 @@ echo {]..a} # {]..a}
# Why?
+# You can tack on prefixes and suffixes.
+echo "Number #"{1..4}, "..."
+ # Number #1, Number #2, Number #3, Number #4, ...
-# Unfortunately, this does not lend itself to parameterization.
+
+# You can concatenate brace-expansion sets.
+echo {1..3}{x..z}" +" "..."
+ # 1x + 1y + 1z + 2x + 2y + 2z + 3x + 3y + 3z + ...
+ # Generates an algebraic expression.
+ # This could be used to find permutations.
+
+# You can nest brace-expansion sets.
+echo {{a..c},{1..3}}
+ # a b c 1 2 3
+ # The "comma operator" splices together strings.
+
+
+# Unfortunately, brace expansion does not lend itself to parameterization.
var1=1
var2=5
echo {$var1..$var2} # {1..5}
@@ -30802,8 +31142,7 @@ fi
scripts to make sure they still work!
As it happens, a couple of the scripts in the
Advanced Bash Scripting Guide had to be
- fixed up (see
- and , for instance).
+ fixed up (see , for instance).
@@ -30886,15 +31225,17 @@ echo $a # 6
In fact, quoting in this context is
not advisable as it may
cause regex evaluation to fail.
- See the Bash
+ FAQ that quoting explicitly disables regex evaluation.
+ See also the
- Ubuntu Bug List
- and and
Wikinerds on Bash syntax.
- With Bash version 3.2.25(1), running on Fedora Core,
- quoting still works, but do not assume this will be the case on
- your machine.
+
+ Setting shopt -s compat31
+ in a script causes reversion to the original
+ behavior.
@@ -30904,11 +31245,396 @@ echo $a # 6
-
-
-
+
+
+
+ Bash, version 4
+
+
+ Chet Ramey announced Version 4 of Bash on the 20th
+ of February, 2009. This release has a number of significant
+ new features, as well as some important bugfixes.
+
+ Among the new goodies:
+
+
+
+
+ Associative arrays.
+
+ An associative array can
+ be thought of as a set of two linked arrays -- one holding
+ the data, and the other the
+ keys that index the individual elements
+ of the data array.
+
+
+
+ A simple address database
+ &fetchaddress;
+
+
+
+ A somewhat more elaborate address database
+ &fetchaddress2;
+
+
+
+
+ Enhancements to the
+ case construct:
+ the ;;& and
+ ;& terminators.
+
+
+ Testing characters
+ &case4;
+
+
+
+
+ The new coproc
+ builtin enables two parallel processes to communicate and
+ interact. As Chet Ramey states in the
+ Bash FAQ
+ Copyright 1995-2009 by Chester Ramey.
+ , ver. 4.01:
+
+
+
+
+ There is a new 'coproc' reserved word that specifies a coprocess:
+ an asynchronous command run with two pipes connected to the creating
+ shell. Coprocs can be named. The input and output file descriptors
+ and the PID of the coprocess are available to the calling shell in
+ variables with coproc-specific names.
+
+
+
+ Coprocesses use file descriptors.
+ File descriptors enable processes and
+ pipes to communicate.
+
+ #!/bin/bash4
+# A coprocess communicates with a while-read loop.
+
+coproc cat $0
+while read -u ${COPROC[0]} line # ${COPROC[0]} is the
+do #+ file descriptor of the coprocess.
+ echo "$line" | sed -e 's/line/NOT-ORIGINAL-TEXT/'
+done
+
+kill $COPROC_PID # No longer need the coprocess,
+ #+ so kill its PID.
+
+ But, be careful!
+
+ #!/bin/bash4
+
+echo; echo
+a=aaa
+b=bbb
+c=ccc
+
+coproc echo "one two three"
+while read -u ${COPROC[0]} a b c; # Note that this loop
+do #+ runs in a subshell.
+ echo "Inside while-read loop: ";
+ echo "a = $a"; echo "b = $b"; echo "c = $c"
+ echo "coproc file descriptor: ${COPROC[0]}"
+done
+
+# a = one
+# b = two
+# c = three
+# So far, so good, but ...
+
+echo "-----------------"
+echo "Outside while-read loop: "
+echo "a = $a" # a =
+echo "b = $b" # b =
+echo "c = $c" # c =
+echo "coproc file descriptor: ${COPROC[0]}"
+echo
+# The coproc is still running, but ...
+#+ it still doesn't enable the parent process
+#+ to "inherit" variables from the child process, the while-read loop.
+
+# Compare this to the "badread.sh" script.
+
+
+ The coprocess is asynchronous,
+ and this might cause a problem. It may terminate before another
+ process has finished communicating with it.
+
+ #!/bin/bash4
+
+coproc cpname { for i in {0..10}; do echo "index = $i"; done; }
+# ^^^^^^ This is a *named* coprocess.
+read -u ${cpname[0]}
+echo $REPLY # index = 0
+echo ${COPROC[0]} #+ No output ... the coprocess timed out
+ # after the first loop iteration.
+
+
+
+
+
+
+ The new mapfile
+ builtin makes it possible to load an array with the contents
+ of a text file without using a loop or command substitution.
+
+ #!/bin/bash4
+
+mapfile Arr1 < $0
+# Same result as Arr1=( $(cat $0) )
+echo "${Arr1[@]}" # Copies this entire script out to stdout.
+
+echo "--"; echo
+
+# But, not the same as read -a !!!
+read -a Arr2 < $0
+echo "${Arr2[@]}" # Reads only first line of script into the array.
+
+exit
+
+
+
+
+ The read builtin got
+ a minor facelift. The
+ timeout option now accepts
+ (decimal) fractional values
+ This only works with pipes and certain other
+ special files.
+ and the option
+ permits preloading the edit buffer.
+ But only in conjunction with
+ readline, i.e.,
+ from the command-line.
+ Unfortunately, these enhancements are still a work in progress
+ and not (yet) usable in scripts.
+
+
+
+
+ Parameter substitution
+ gets case-modification operators.
+
+#!/bin/bash4
+
+var=veryMixedUpVariable
+echo ${var} # veryMixedUpVariable
+echo ${var^} # VeryMixedUpVariable
+# * First char --> uppercase.
+echo ${var^^} # VERYMIXEDUPVARIABLE
+# ** All chars --> uppercase.
+echo ${var,} # veryMixedUpVariable
+# * First char --> lowercase.
+echo ${var,,} # verymixedupvariable
+# ** All chars --> lowercase.
+
+
+
+
+ The declare builtin now
+ accepts the lowercase
+ and capitalize
+ options.
+
+#!/bin/bash4
+
+declare -l var1 # Will change to lowercase
+var1=MixedCaseVARIABLE
+echo "$var1" # mixedcasevariable
+# Same effect as echo $var1 | tr A-Z a-z
+
+declare -c var2 # Changes only initial char to uppercase.
+var2=originally_lowercase
+echo "$var2" # Originally_lowercase
+# NOT the same effect as echo $var2 | tr a-z A-Z
+
+
+
+
+ Brace expansion has more options.
+
+ Increment/decrement, specified in the
+ final term within braces.
+ #!/bin/bash4
+
+echo {40..60..2}
+# 40 42 44 46 48 50 52 54 56 58 60
+# All the even numbers, between 40 and 60.
+
+echo {60..40..2}
+# 60 58 56 54 52 50 48 46 44 42 40
+# All the even numbers, between 40 and 60, counting backwards.
+# In effect, a decrement.
+echo {60..40..-2}
+# The same output. The minus sign is not necessary.
+
+# But, what about letters and symbols?
+echo {X..d}
+# X Y Z [ ] ^ _ ` a b c d
+echo {X..d..2}
+# X Z ^ ` b d
+# It seems to work for upper/lowercase letters,
+#+ but the increment is a bit inconsistent on symbols.
+
+ Zero-padding, specified in the
+ first term within braces, prefixes each term in the output
+ with the same number of zeroes.
+
+
+bash4$ echo {010..15}
+010 011 012 013 014 015
+
+
+bash4$ echo {000..10}
+000 001 002 003 004 005 006 007 008 009 010
+
+
+
+
+
+
+ Substring
+ extraction on positional
+ parameters now starts with $0 as the
+ zero-index. (This corrects an
+ inconsistency in the treatment of positional parameters.)
+
+ #!/bin/bash4
+# show-params.bash4
+
+# Invoke this scripts with at least one positional parameter.
+
+E_BADPARAMS=99
+
+if [ -z "$1" ]
+then
+ echo "Usage $0 param1 ..."
+ exit $E_BADPARAMS
+fi
+
+echo ${@:0}
+
+# bash3 show-params.bash4 one two three
+# one two three
+
+# bash4 show-params.bash4 one two three
+# show-params.bash4 one two three
+
+# $0 $1 $2 $3
+
+
+
+
+ The new **
+ globbing operator
+ matches filenames and directories
+ recursively.
+
+ #!/bin/bash4
+# filelist.bash4
+
+shopt -s globstar # Must enable globstar, otherwise ** doesn't work.
+ # The globstar shell option is new to version 4 of Bash.
+
+echo "Using *"; echo
+for filename in *
+do
+ echo "$filename"
+done # Lists only files in current directory ($PWD).
+
+echo; echo "--------------"; echo
+
+echo "Using **"
+for filename in **
+do
+ echo "$filename"
+done # Lists complete file tree, recursively.
+
+exit
+
+Using *
+
+allmyfiles
+filelist.bash4
+
+--------------
+
+Using **
+
+allmyfiles
+allmyfiles/file.index.txt
+allmyfiles/my_music
+allmyfiles/my_music/me-singing-60s-folksongs.ogg
+allmyfiles/my_music/me-singing-opera.ogg
+allmyfiles/my_music/piano-lesson.1.ogg
+allmyfiles/my_pictures
+allmyfiles/my_pictures/at-beach-with-Jade.png
+allmyfiles/my_pictures/picnic-with-Melissa.png
+filelist.bash4
+
+
+
+
+ The new $BASHPID
+ internal variable.
+
+
+
+
+ There is a new builtin
+ error-handling function named
+ command_not_found_handle.
+ #!/bin/bash4
+
+command_not_found_handle ()
+{ # Accepts implicit parameters.
+ echo "The following command is not valid: \""$1\"""
+ echo "With the following argument(s): \""$2\"" \""$3\""" # $4, $5 ...
+} # $1, $2, etc. are not explicitly passed to the function.
+
+bad_command arg1 arg2
+
+# The following command is not valid: "bad_command"
+# With the following argument(s): "arg1" "arg2"
+
+
+
+
+
+ Editorial comment
+ Associative arrays? Coprocesses? Whatever happened
+ to the lean and mean Bash we have come to know and love?
+ Could it be suffering from (horrors!) feature
+ creep? Or perhaps even Korn shell envy?
+ Note to Chet Ramey: Please add only
+ essential features in future Bash
+ releases -- perhaps for-each
+ loops and support for multi-dimensional arrays. Most
+ Bash users won't need, won't use, and likely won't greatly
+ appreciate complex features like built-in debuggers,
+ Perl interfaces, and bolt-on rocket boosters.
+
+
+
+
+
+
+
+
+
@@ -30967,7 +31693,10 @@ echo $a # 6
special qualifications,
In fact, he is a school dropout
and has no formal credentials or qualifications
- whatsoever.
+ whatsoever. Aside from the ABS Guide,
+ his main claim to fame is a First Place in the sack
+ race at the Colfax Elementary School Field Day in June,
+ 1958.
other than a compulsion to write.
Those who can, do. Those who can't . . . get an
MCSE.
@@ -31235,9 +31964,9 @@ echo $a # 6
Benno Schulenberg, Tedman Eng, Jochen DeSmet, Juan Nicolas Ruiz,
Oliver Beckstein, Achmed Darwish, Dotan Barak, Richard Neill,
Albert Siersema, Omair Eshkenazi, Geoff Lee, JuanJo Ciarlante,
- Cliff Bamford, Nathan Coulter, Antonio Macchi, Andreas Kühne,
- Pádraig Brady, and David Lawyer (himself an author of
- four HOWTOs).
+ Cliff Bamford, Nathan Coulter, Antonio Macchi, Tomas Pospisek,
+ Andreas Kühne, Pádraig Brady, and David Lawyer
+ (himself an author of four HOWTOs).
My gratitude to Chet
Ramey and Brian Fox for writing Bash,
@@ -31584,7 +32313,7 @@ echo $a # 6
19730-691-02356-5
- The classic tutorial on problem solving methods
+ The classic tutorial on problem-solving methods
(i.e., algorithms), with special emphasis on how to teach them.*
@@ -31818,9 +32547,17 @@ echo $a # 6
- Chet Ramey's Bash FAQ..
- This site carries the latest version of the FAQ.
+ Chet Ramey's Bash FAQ,
+ and mirror
+ site.
+
+
+
+
+
+
+ Greg's WIKI: Bash FAQ.
@@ -31872,6 +32609,14 @@ echo $a # 6
+
+
+ Example shell scripts at joyent.
+
+
+
+
Steve Parker's
+
+
+ An excellent collection of Bash scripting tips, tricks,
+ and resources at the Bash Hackers
+ Wiki.
+
+
+
Giles Orr's
+
+
+ Shelltris and shellitaire
+ at Shell Script
+ Games.
+
+
+
Mark Komarinski's
+
+
+ The Wikipedia
+ article covering dc.
+
+
+
The manpages for
@@ -32239,7 +33009,7 @@ echo $a # 6
+++
- The following two scripts are by Mark Moraes of the University
+ The following script is by Mark Moraes of the University
of Toronto. See the file Moraes-COPYRIGHT
for permissions and restrictions. This file is included in the
combined HTML/source tarball
@@ -32251,11 +33021,6 @@ echo $a # 6
&behead;
-
- ftpget: Downloading files via ftp
- &ftpget;
-
-
+Antek Sawicki contributed the following script, which makes very
@@ -32335,11 +33100,6 @@ echo $a # 6
Stéphane Chazelas demonstrates object-oriented programming in a
Bash script.
-
- Object-oriented database
- &objoriented;
-
-
Mariusz Gniazdowski contributed a hash
library for use in scripts.
@@ -32514,6 +33274,25 @@ echo $a # 6
&msquare;
+
+ Fifteen Puzzle
+ &fifteen;
+
+
+
+
+ The Towers of Hanoi, graphic
+ version
+ &hanoi2;
+
+
+
+
+ The Towers of Hanoi, alternate graphic
+ version
+ &hanoi2a;
+
+
An alternate version of the
getopt-simple.sh script
@@ -36707,6 +37486,11 @@ thegrendel@theriver.com26 Jan 2009WORCESTERBERRY release: Minor update.
+
+
+ 23 Mar 2009
+ THIMBLEBERRY release: Major update.
+
@@ -36723,7 +37507,7 @@ thegrendel@theriver.com
bzip2-ed
tarball including both the SGML source
and rendered HTML, may be downloaded from the author's
+ url="http://bash.neuralshortcircuit.com/abs-guide-latest.tar.bz2">author's
home site).
A These comments added by author of this document.
@@ -19,7 +18,33 @@ else
done
fi
+exit
+
# ==> Exercise: Add error checking and other options.
# ==>
# ==> Note that the small sed script repeats, except for the arg passed.
# ==> Does it make sense to embed it in a function? Why or why not?
+
+
+/*
+ * Copyright University of Toronto 1988, 1989.
+ * Written by Mark Moraes
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ *
+ * 1. The author and the University of Toronto are not responsible
+ * for the consequences of use of this software, no matter how awful,
+ * even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ *
+ * 4. This notice may not be removed or altered.
+ */
diff --git a/LDP/guide/docbook/abs-guide/case4.sh b/LDP/guide/docbook/abs-guide/case4.sh
new file mode 100644
index 00000000..3da68d1d
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/case4.sh
@@ -0,0 +1,40 @@
+#!/bin/bash4
+
+test_char ()
+{
+ case "$1" in
+ [[:print:]] ) echo "$1 is a printable character.";;& # |
+ # The ;;& terminator continues to the next pattern test. |
+ [[:alnum:]] ) echo "$1 is an alpha/numeric character.";;& # v
+ [[:alpha:]] ) echo "$1 is an alphabetic character.";;& # v
+ [[:lower:]] ) echo "$1 is a lowercase alphabetic character.";;&
+ [[:digit:]] ) echo "$1 is an numeric character.";& # |
+ # The ;& terminator executes the next statement ... # |
+ %%%@@@@@ ) echo "********************************";; # v
+# ^^^^^^^^ ... even with a dummy pattern.
+ esac
+}
+
+echo
+
+test_char 3
+# 3 is a printable character.
+# 3 is an alpha/numeric character.
+# 3 is an numeric character.
+# ********************************
+echo
+
+test_char m
+# m is a printable character.
+# m is an alpha/numeric character.
+# m is an alphabetic character.
+# m is a lowercase alphabetic character.
+echo
+
+test_char /
+# / is a printable character.
+
+echo
+
+# The ;;& terminator can save complex if/then conditions.
+# The ;& is somewhat less useful.
diff --git a/LDP/guide/docbook/abs-guide/copy-cd.sh b/LDP/guide/docbook/abs-guide/copy-cd.sh
index dc8c320a..debec553 100644
--- a/LDP/guide/docbook/abs-guide/copy-cd.sh
+++ b/LDP/guide/docbook/abs-guide/copy-cd.sh
@@ -5,9 +5,9 @@ CDROM=/dev/cdrom # CD ROM device
OF=/home/bozo/projects/cdimage.iso # output file
# /xxxx/xxxxxxxx/ Change to suit your system.
BLOCKSIZE=2048
-SPEED=10 # May use higher speed ...
-DEVICE=/dev/cdrom
-# DEVICE="0,0" on older versions of cdrecord.
+# SPEED=10 # If unspecified, uses max spd.
+# DEVICE=/dev/cdrom older version.
+DEVICE="1,0,0"
echo; echo "Insert source CD, but do *not* mount it."
echo "Press ENTER when ready. "
@@ -26,7 +26,8 @@ read ready # Wait for input, $ready not used.
echo "Copying $OF to CDR."
-cdrecord -v -isosize speed=$SPEED dev=$DEVICE $OF
+# cdrecord -v -isosize speed=$SPEED dev=$DEVICE $OF # Old version.
+wodim -v -isosize dev=$DEVICE $OF
# Uses Joerg Schilling's "cdrecord" package (see its docs).
# http://www.fokus.gmd.de/nthp/employees/schilling/cdrecord.html
# Newer Linux distros may use "wodim" rather than "cdrecord" ...
diff --git a/LDP/guide/docbook/abs-guide/ex40.sh b/LDP/guide/docbook/abs-guide/ex40.sh
index 88141dfb..568542bc 100644
--- a/LDP/guide/docbook/abs-guide/ex40.sh
+++ b/LDP/guide/docbook/abs-guide/ex40.sh
@@ -6,8 +6,8 @@
SPEED=10 # May use higher speed if your hardware supports it.
IMAGEFILE=cdimage.iso
CONTENTSFILE=contents
-DEVICE=/dev/cdrom
-# DEVICE="0,0" For older versions of cdrecord
+# DEVICE=/dev/cdrom For older versions of cdrecord
+DEVICE="1,0,0"
DEFAULTDIR=/opt # This is the directory containing the data to be burned.
# Make sure it exists.
# Exercise: Add a test for this.
@@ -41,8 +41,10 @@ echo "Creating ISO9660 file system image ($IMAGEFILE)."
# Burn the CDR.
echo "Burning the disk."
echo "Please be patient, this will take a while."
-cdrecord -v -isosize speed=$SPEED dev=$DEVICE $IMAGEFILE
-# In newer Linux distros, the "wodim" utility may assume the
+wodim -v -isosize dev=$DEVICE $IMAGEFILE
+# In newer Linux distros, the "wodim" utility assumes the
#+ functionality of "cdrecord."
+exitcode=$?
+echo "Exit code = $exitcode"
-exit $?
+exit $exitcode
diff --git a/LDP/guide/docbook/abs-guide/ex72.sh b/LDP/guide/docbook/abs-guide/ex72.sh
index 536c4ea0..72542ec1 100644
--- a/LDP/guide/docbook/abs-guide/ex72.sh
+++ b/LDP/guide/docbook/abs-guide/ex72.sh
@@ -29,7 +29,8 @@ Password="your.e-mail.address" # Change above to suit.
ftp -n $Server <<End-Of-Session
# -n option disables auto-logon
-user anonymous "$Password"
+user anonymous "$Password" # If this doesn't work, then try:
+ # quote user anonymous "$Password"
binary
bell # Ring 'bell' after each file transfer.
cd $Directory
diff --git a/LDP/guide/docbook/abs-guide/fetch_address-2.sh b/LDP/guide/docbook/abs-guide/fetch_address-2.sh
new file mode 100644
index 00000000..6d94adf3
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/fetch_address-2.sh
@@ -0,0 +1,50 @@
+#!/bin/bash4
+# fetch_address-2.sh
+# A more elaborate version of fetch_address.sh.
+
+SUCCESS=0
+E_DB=99 # Error code for missing entry.
+
+declare -A address
+# -A option declares associative array.
+
+
+store_address ()
+{
+ address[$1]="$2"
+ return $?
+}
+
+
+fetch_address ()
+{
+ if [[ -z "${address[$1]}" ]]
+ then
+ echo "$1's address is not in database."
+ return $E_DB
+ fi
+
+ echo "$1's address is ${address[$1]}."
+ return $?
+}
+
+
+store_address "Charles Jones" "414 W. 10th Ave., Baltimore, MD 21236"
+store_address "John Smith" "202 E. 3rd St., New York, NY 10009"
+store_address "Wilma Wilson" "1854 Vermont Ave, Los Angeles, CA 90023"
+# Exercise:
+# Rewrite the above store_address calls to read data from a file,
+#+ then assign field 1 to name, field 2 to address in the array.
+# Each line in the file would have a format corresponding to the above.
+# Use a while-read loop to read from file, sed or awk to parse the fields.
+
+fetch_address "Charles Jones"
+# Charles Jones's address is 414 W. 10th Ave., Baltimore, MD 21236.
+fetch_address "Wilma Wilson"
+# Wilma Wilson's address is 1854 Vermont Ave, Los Angeles, CA 90023.
+fetch_address "John Smith"
+# John Smith's address is 202 E. 3rd St., New York, NY 10009.
+fetch_address "Bozo Bozeman"
+# Bozo Bozeman's address is not in database.
+
+exit $? # In this case, exit code = 99, since that is function return.
diff --git a/LDP/guide/docbook/abs-guide/fetch_address.sh b/LDP/guide/docbook/abs-guide/fetch_address.sh
new file mode 100644
index 00000000..7cae768f
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/fetch_address.sh
@@ -0,0 +1,17 @@
+#!/bin/bash4
+# fetch_address.sh
+
+declare -A address
+# -A option declares associative array.
+
+address[Charles]="414 W. 10th Ave., Baltimore, MD 21236"
+address[John]="202 E. 3rd St., New York, NY 10009"
+address[Wilma]="1854 Vermont Ave, Los Angeles, CA 90023"
+
+
+echo "Charles's address is ${address[Charles]}."
+# Charles's address is 414 W. 10th Ave., Baltimore, MD 21236.
+echo "Wilma's address is ${address[Wilma]}."
+# Wilma's address is 1854 Vermont Ave, Los Angeles, CA 90023.
+echo "John's address is ${address[John]}."
+# John's address is 202 E. 3rd St., New York, NY 10009.
diff --git a/LDP/guide/docbook/abs-guide/fifteen.sh b/LDP/guide/docbook/abs-guide/fifteen.sh
new file mode 100644
index 00000000..9b2fad42
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/fifteen.sh
@@ -0,0 +1,173 @@
+#!/bin/bash
+# fifteen.sh
+
+# Classic "Fifteen Puzzle"
+# Author: Antonio Macchi
+# Lightly edited and commented by ABS Guide author.
+# Used in ABS Guide with permission. (Thanks!)
+
+# The invention of the Fifteen Puzzle is attributed to either
+#+ Sam Loyd or Noyes Palmer Chapman.
+# The puzzle was wildly popular in the late 19th-century.
+
+# Object: Rearrange the numbers so they read in order,
+#+ from 1 - 15: ________________
+# | 1 2 3 4 |
+# | 5 6 7 8 |
+# | 9 10 11 12 |
+# | 13 14 15 |
+# ----------------
+
+
+#######################
+# Constants #
+ SQUARES=16 #
+ FAIL=70 #
+ E_PREMATURE_EXIT=80 #
+#######################
+
+
+########
+# Data #
+########
+
+Puzzle=( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " " )
+
+
+#############
+# Functions #
+#############
+
+function swap
+{
+ local tmp
+
+ tmp=${Puzzle[$1]}
+ Puzzle[$1]=${Puzzle[$2]}
+ Puzzle[$2]=$tmp
+}
+
+
+function Jumble
+{ # Scramble the pieces at beginning of round.
+ local i pos1 pos2
+
+ for i in {1..100}
+ do
+ pos1=$(( $RANDOM % $SQUARES))
+ pos2=$(( $RANDOM % $SQUARES ))
+ swap $pos1 $pos2
+ done
+}
+
+
+function PrintPuzzle
+{
+ local i1 i2 puzpos
+ puzpos=0
+
+ clear
+ echo "Enter quit to exit."; echo # Better that than Ctl-C.
+
+ echo ",----.----.----.----." # Top border.
+ for i1 in {1..4}
+ do
+ for i2 in {1..4}
+ do
+ printf "| %2s " "${Puzzle[$puzpos]}"
+ (( puzpos++ ))
+ done
+ echo "|" # Right-side border.
+ test $i1 = 4 || echo "+----+----+----+----+"
+ done
+ echo "'----'----'----'----'" # Bottom border.
+}
+
+
+function GetNum
+{ # Test for valid input.
+ local puznum garbage
+
+ while true
+ do
+ echo "Moves: $moves" # Also counts invalid moves.
+ read -p "Number to move: " puznum garbage
+ if [ "$puznum" = "quit" ]; then echo; exit $E_PREMATURE_EXIT; fi
+ test -z "$puznum" -o -n "${puznum//[0-9]/}" && continue
+ test $puznum -gt 0 -a $puznum -lt $SQUARES && break
+ done
+ return $puznum
+}
+
+
+function GetPosFromNum
+{ # $1 = puzzle-number
+ local puzpos
+
+ for puzpos in {0..15}
+ do
+ test "${Puzzle[$puzpos]}" = "$1" && break
+ done
+ return $puzpos
+}
+
+
+function Move
+{ # $1=Puzzle-pos
+ test $1 -gt 3 && test "${Puzzle[$(( $1 - 4 ))]}" = " "\
+ && swap $1 $(( $1 - 4 )) && return 0
+ test $(( $1%4 )) -ne 3 && test "${Puzzle[$(( $1 + 1 ))]}" = " "\
+ && swap $1 $(( $1 + 1 )) && return 0
+ test $1 -lt 12 && test "${Puzzle[$(( $1 + 4 ))]}" = " "\
+ && swap $1 $(( $1 + 4 )) && return 0
+ test $(( $1%4 )) -ne 0 && test "${Puzzle[$(( $1 - 1 ))]}" = " " &&\
+ swap $1 $(( $1 - 1 )) && return 0
+ return 1
+}
+
+
+function Solved
+{
+ local pos
+
+ for pos in {0..14}
+ do
+ test "${Puzzle[$pos]}" = $(( $pos + 1 )) || return $FAIL
+ # Check whether number in each square = square number.
+ done
+ return 0 # Successful solution.
+}
+
+
+################### MAIN () ########################
+moves=0
+Jumble
+
+while true # Loop continuously until puzzle solved.
+do
+ echo; echo
+ PrintPuzzle
+ echo
+ while true
+ do
+ GetNum
+ puznum=$?
+ GetPosFromNum $puznum
+ puzpos=$?
+ ((moves++))
+ Move $puzpos && break
+ done
+ Solved && break
+done
+
+echo;echo
+PrintPuzzle
+echo; echo "BRAVO!"; echo
+
+exit 0
+####################################################
+
+# Exercise:
+# --------
+# Rewrite the script to display the letters A - O,
+#+ rather than the numbers 1 - 15.
diff --git a/LDP/guide/docbook/abs-guide/hanoi2.bash b/LDP/guide/docbook/abs-guide/hanoi2.bash
new file mode 100644
index 00000000..75cfde4d
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/hanoi2.bash
@@ -0,0 +1,202 @@
+#! /bin/bash
+# The Towers Of Hanoi
+# Original script (hanoi.bash) copyright (C) 2000 Amit Singh.
+# All Rights Reserved.
+# http://hanoi.kernelthread.com
+
+# hanoi2.bash
+# Version 2: modded for ASCII-graphic display.
+# Uses code contributed by Antonio Macchi,
+#+ with heavy editing by ABS Guide author.
+# This variant also falls under the original copyright, see above.
+# Used in ABS Guide with Amit Singh's permission (thanks!).
+
+
+# Variables #
+E_NOPARAM=86
+E_BADPARAM=87 # Illegal no. of disks passed to script.
+E_NOEXIT=88
+DISKS=$1
+Moves=0
+
+MWIDTH=7
+MARGIN=2
+# Arbitrary "magic" constants, work okay for relatively small # of disks.
+# BASEWIDTH=51 # Original code.
+let "basewidth = $MWIDTH * $DISKS + $MARGIN" # "Base" beneath rods.
+# Above "algorithm" could likely stand improvement.
+
+# Display variables.
+let "disks1 = $DISKS - 1"
+let "spaces1 = $DISKS"
+let "spaces2 = 2 * $DISKS"
+
+let "lastmove_t = $DISKS - 1" # Final move?
+
+
+declare -a Rod1 Rod2 Rod3
+
+#################
+
+
+function repeat { # $1=char $2=number of repetitions
+ local n # Repeat-print a character.
+
+ for (( n=0; n<$2; n++ )); do
+ echo -n "$1"
+ done
+}
+
+function FromRod {
+ local rod summit weight sequence
+
+ while true; do
+ rod=$1
+ test ${rod/[^123]/} || continue
+
+ sequence=$(echo $(seq 0 $disks1 | tac))
+ for summit in $sequence; do
+ eval weight=\${Rod${rod}[$summit]}
+ test $weight -ne 0 &&
+ { echo "$rod $summit $weight"; return; }
+ done
+ done
+}
+
+
+function ToRod { # $1=previous (FromRod) weight
+ local rod firstfree weight sequence
+
+ while true; do
+ rod=$2
+ test ${rod/[^123]} || continue
+
+ sequence=$(echo $(seq 0 $disks1 | tac))
+ for firstfree in $sequence; do
+ eval weight=\${Rod${rod}[$firstfree]}
+ test $weight -gt 0 && { (( firstfree++ )); break; }
+ done
+ test $weight -gt $1 -o $firstfree = 0 &&
+ { echo "$rod $firstfree"; return; }
+ done
+}
+
+
+function PrintRods {
+ local disk rod empty fill sp sequence
+
+
+ repeat " " $spaces1
+ echo -n "|"
+ repeat " " $spaces2
+ echo -n "|"
+ repeat " " $spaces2
+ echo "|"
+
+ sequence=$(echo $(seq 0 $disks1 | tac))
+ for disk in $sequence; do
+ for rod in {1..3}; do
+ eval empty=$(( $DISKS - (Rod${rod}[$disk] / 2) ))
+ eval fill=\${Rod${rod}[$disk]}
+ repeat " " $empty
+ test $fill -gt 0 && repeat "*" $fill || echo -n "|"
+ repeat " " $empty
+ done
+ echo
+ done
+ repeat "=" $basewidth # Print "base" beneath rods.
+ echo
+}
+
+
+display ()
+{
+ echo
+ PrintRods
+
+ # Get rod-number, summit and weight
+ first=( `FromRod $1` )
+ eval Rod${first[0]}[${first[1]}]=0
+
+ # Get rod-number and first-free position
+ second=( `ToRod ${first[2]} $2` )
+ eval Rod${second[0]}[${second[1]}]=${first[2]}
+
+
+echo; echo; echo
+if [ "${Rod3[lastmove_t]}" = 1 ]
+then # Last move? If yes, then display final position.
+ echo "+ Final Position: $Moves moves"; echo
+ PrintRods
+ fi
+}
+
+# From here down, almost the same as original (hanoi.bash) script.
+
+dohanoi() { # Recursive function.
+ case $1 in
+ 0)
+ ;;
+ *)
+ dohanoi "$(($1-1))" $2 $4 $3
+ if [ "$Moves" -ne 0 ]
+ then
+ echo "+ Position after move $Moves"
+ fi
+ ((Moves++))
+ echo -n " Next move will be: "
+ echo $2 "-->" $3
+ display $2 $3
+ dohanoi "$(($1-1))" $4 $3 $2
+ ;;
+ esac
+}
+
+setup_arrays ()
+{
+ local dim n elem
+
+ let "dim1 = $1 - 1"
+ elem=$dim1
+
+ for n in $(seq 0 $dim1)
+ do
+ let "Rod1[$elem] = 2 * $n + 1"
+ Rod2[$n]=0
+ Rod3[$n]=0
+ ((elem--))
+ done
+}
+
+
+### Main ###
+
+setup_arrays $DISKS
+echo; echo "+ Start Position"
+
+case $# in
+ 1) case $(($1>0)) in # Must have at least one disk.
+ 1)
+ disks=$1
+ dohanoi $1 1 3 2
+# Total moves = 2^n - 1, where n = # of disks.
+ echo
+ exit 0;
+ ;;
+ *)
+ echo "$0: Illegal value for number of disks";
+ exit $E_BADPARAM;
+ ;;
+ esac
+ ;;
+ *)
+ echo "usage: $0 N"
+ echo " Where \"N\" is the number of disks."
+ exit $E_NOPARAM;
+ ;;
+esac
+
+exit $E_NOEXIT # Shouldn't exit here.
+
+# Note:
+# Redirect script output to a file, otherwise it scrolls off display.
diff --git a/LDP/guide/docbook/abs-guide/hanoi2a.bash b/LDP/guide/docbook/abs-guide/hanoi2a.bash
new file mode 100644
index 00000000..5c4de22e
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/hanoi2a.bash
@@ -0,0 +1,216 @@
+#! /bin/bash
+# The Towers Of Hanoi
+# Original script (hanoi.bash) copyright (C) 2000 Amit Singh.
+# All Rights Reserved.
+# http://hanoi.kernelthread.com
+
+# hanoi2.bash
+# Version 2: modded for ASCII-graphic display.
+# Uses code contributed by Antonio Macchi,
+#+ with heavy editing by ABS Guide author.
+# This variant also falls under the original copyright, see above.
+# Used in ABS Guide with Amit Singh's permission (thanks!).
+
+
+# Variables #
+E_NOPARAM=86
+E_BADPARAM=87 # Illegal no. of disks passed to script.
+E_NOEXIT=88
+DELAY=2 # Interval, in seconds, between moves. Change, if desired.
+DISKS=$1
+Moves=0
+
+MWIDTH=7
+MARGIN=2
+# Arbitrary "magic" constants, work okay for relatively small # of disks.
+# BASEWIDTH=51 # Original code.
+let "basewidth = $MWIDTH * $DISKS + $MARGIN" # "Base" beneath rods.
+# Above "algorithm" could likely stand improvement.
+
+# Display variables.
+let "disks1 = $DISKS - 1"
+let "spaces1 = $DISKS"
+let "spaces2 = 2 * $DISKS"
+
+let "lastmove_t = $DISKS - 1" # Final move?
+
+
+declare -a Rod1 Rod2 Rod3
+
+#################
+
+
+function repeat { # $1=char $2=number of repetitions
+ local n # Repeat-print a character.
+
+ for (( n=0; n<$2; n++ )); do
+ echo -n "$1"
+ done
+}
+
+function FromRod {
+ local rod summit weight sequence
+
+ while true; do
+ rod=$1
+ test ${rod/[^123]/} || continue
+
+ sequence=$(echo $(seq 0 $disks1 | tac))
+ for summit in $sequence; do
+ eval weight=\${Rod${rod}[$summit]}
+ test $weight -ne 0 &&
+ { echo "$rod $summit $weight"; return; }
+ done
+ done
+}
+
+
+function ToRod { # $1=previous (FromRod) weight
+ local rod firstfree weight sequence
+
+ while true; do
+ rod=$2
+ test ${rod/[^123]} || continue
+
+ sequence=$(echo $(seq 0 $disks1 | tac))
+ for firstfree in $sequence; do
+ eval weight=\${Rod${rod}[$firstfree]}
+ test $weight -gt 0 && { (( firstfree++ )); break; }
+ done
+ test $weight -gt $1 -o $firstfree = 0 &&
+ { echo "$rod $firstfree"; return; }
+ done
+}
+
+
+function PrintRods {
+ local disk rod empty fill sp sequence
+
+ tput cup 5 0
+
+ repeat " " $spaces1
+ echo -n "|"
+ repeat " " $spaces2
+ echo -n "|"
+ repeat " " $spaces2
+ echo "|"
+
+ sequence=$(echo $(seq 0 $disks1 | tac))
+ for disk in $sequence; do
+ for rod in {1..3}; do
+ eval empty=$(( $DISKS - (Rod${rod}[$disk] / 2) ))
+ eval fill=\${Rod${rod}[$disk]}
+ repeat " " $empty
+ test $fill -gt 0 && repeat "*" $fill || echo -n "|"
+ repeat " " $empty
+ done
+ echo
+ done
+ repeat "=" $basewidth # Print "base" beneath rods.
+ echo
+}
+
+
+display ()
+{
+ echo
+ PrintRods
+
+ # Get rod-number, summit and weight
+ first=( `FromRod $1` )
+ eval Rod${first[0]}[${first[1]}]=0
+
+ # Get rod-number and first-free position
+ second=( `ToRod ${first[2]} $2` )
+ eval Rod${second[0]}[${second[1]}]=${first[2]}
+
+
+ if [ "${Rod3[lastmove_t]}" = 1 ]
+ then # Last move? If yes, then display final position.
+ tput cup 0 0
+ echo; echo "+ Final Position: $Moves moves"
+ PrintRods
+ fi
+
+ sleep $DELAY
+}
+
+# From here down, almost the same as original (hanoi.bash) script.
+
+dohanoi() { # Recursive function.
+ case $1 in
+ 0)
+ ;;
+ *)
+ dohanoi "$(($1-1))" $2 $4 $3
+ if [ "$Moves" -ne 0 ]
+ then
+ tput cup 0 0
+ echo; echo "+ Position after move $Moves"
+ fi
+ ((Moves++))
+ echo -n " Next move will be: "
+ echo $2 "-->" $3
+ display $2 $3
+ dohanoi "$(($1-1))" $4 $3 $2
+ ;;
+ esac
+}
+
+setup_arrays ()
+{
+ local dim n elem
+
+ let "dim1 = $1 - 1"
+ elem=$dim1
+
+ for n in $(seq 0 $dim1)
+ do
+ let "Rod1[$elem] = 2 * $n + 1"
+ Rod2[$n]=0
+ Rod3[$n]=0
+ ((elem--))
+ done
+}
+
+
+### Main ###
+
+trap "tput cnorm" 0
+tput civis
+clear
+
+setup_arrays $DISKS
+
+tput cup 0 0
+echo; echo "+ Start Position"
+
+case $# in
+ 1) case $(($1>0)) in # Must have at least one disk.
+ 1)
+ disks=$1
+ dohanoi $1 1 3 2
+# Total moves = 2^n - 1, where n = # of disks.
+ echo
+ exit 0;
+ ;;
+ *)
+ echo "$0: Illegal value for number of disks";
+ exit $E_BADPARAM;
+ ;;
+ esac
+ ;;
+ *)
+ echo "usage: $0 N"
+ echo " Where \"N\" is the number of disks."
+ exit $E_NOPARAM;
+ ;;
+esac
+
+exit $E_NOEXIT # Shouldn't exit here.
+
+# Exercise:
+# --------
+# There is a minor bug in the script that causes the display of
+#+ the next-to-last move to be skipped.
+#+ Fix this.
diff --git a/LDP/guide/docbook/abs-guide/ind-ref.sh b/LDP/guide/docbook/abs-guide/ind-ref.sh
index 476558aa..c235faad 100644
--- a/LDP/guide/docbook/abs-guide/ind-ref.sh
+++ b/LDP/guide/docbook/abs-guide/ind-ref.sh
@@ -10,8 +10,10 @@ echo "\$var = $var" # $var = 23
# So far, everything as expected. But ...
echo "\$\$var = $$var" # $$var = 4570var
-# Not meaningful. The contents of a memory location pointed to?
-# Not useful at this point.
+# Not useful ...
+# \$\$ expanded to PID of process being executed,
+#+ and "var" is echoed as plain text.
+# (Thank you, Jakob Bohm, for pointing this out.)
echo "\\\$\$var = \$$var" # \$$var = $23
# As expected. The first $ is escaped and pasted on to
diff --git a/LDP/guide/docbook/abs-guide/wr-ps.bash b/LDP/guide/docbook/abs-guide/wr-ps.bash
new file mode 100644
index 00000000..ada8f8f4
--- /dev/null
+++ b/LDP/guide/docbook/abs-guide/wr-ps.bash
@@ -0,0 +1,65 @@
+#!/bin/bash
+# wr-ps.bash: while-read loop with process substitution.
+
+# This example contributed by Tomas Pospisek.
+# (Heavily edited by the ABS Guide author.)
+
+echo
+
+echo "random input" | while read i
+do
+ global=3D": Not available outside the loop."
+ # ... because it runs in a subshell.
+done
+
+echo "\$global (from outside the subprocess) = $global"
+# $global (from outside the subprocess) =
+
+echo; echo "--"; echo
+
+while read i
+do
+ echo $i
+ global=3D": Available outside the loop."
+ # ... because it does *not* run in a subshell.
+done < <( echo "random input" )
+# ^ ^
+
+echo "\$global (using process substitution) = $global"
+# random input
+# $global (using process substitution) = 3D: Available outside the loop.
+
+
+echo; echo "##########"; echo
+
+
+
+# And likewise . . .
+
+declare -a inloop
+index=0
+cat $0 | while read line
+do
+ inloop[$index]="$line"
+ ((index++))
+ # It runs in a subshell, so ...
+done
+echo "OUTPUT = "
+echo ${inloop[*]} # ... nothing echoes.
+
+
+echo; echo "--"; echo
+
+
+declare -a outloop
+index=0
+while read line
+do
+ outloop[$index]="$line"
+ ((index++))
+ # It does *not* run in a subshell, so ...
+done < <( cat $0 )
+echo "OUTPUT = "
+echo ${outloop[*]} # ... the entire script echoes.
+
+exit $?