This commit is contained in:
gferg 2005-03-21 13:51:11 +00:00
parent d73bf4f9df
commit 07176b0865
48 changed files with 768 additions and 326 deletions

View File

@ -6,6 +6,118 @@
http://personal.riverusers.com/~thegrendel/Change.log
------------------------------------------------------------------------
Version 3.3
Raspberry release, 03/20/05
1) In the "Starting Off With a Sha-Bang" chapter:
Amended footnote [3] to mention a cat / here document.
(Thank you, Fabian Kreutz.)
Fixed typo in "ex1a.sh" example.
(Thank you, Preetam.)
Added Larry Wall epigraph.
Changed "Important" block to "Tip," and added "generalizing scripts"
paragraph.
2) In "Special Characters" chapter:
At "#" entry, noted that if comment follows a command on a line,
then whitespace preceding the "#" is necessary.
(Thanks, Le Wen.)
3) In "Basic Commands" section of "External Commands" Chapter:
Greatly expanded discussion of "chattr" entry.
4) In "File and Archiving Commands" section of "External Commands" Chapter:
Added "rpm -qf" tip at "rpm" entry.
5) In "Text Processing" section of "External Commands" Chapter:
Added "enscript" entry.
At "egrep" and "fgrep" entries.
added symbolic link note
added "dict-lookup.sh" example script.
Updated "wc" entry.
6) In "Communications Commands" section of "External Commands" chapter:
Added "netconfig" entry.
7) In "Math Commands" section of "External Commands" chapter:
Fixup of "hexconvert.sh" example script
(had left out initialization of E_NOARGS variable)
(Thanks, Stefano Palmeri.)
8) In "Internal Commands and Builtins" chapter:
At "forking/spawning" sidebar:
Added "spawn.sh" example
9) In "Job Control Commands" section of "Internal Commands and Builtins"
chapter:
Corrected note discussing zombie processes.
(Thank you, Alan Sundell.)
10) In "Here Documents" chapter:
Removed reference to 'telnet' -- since it's generally not a good idea.
11) In "Of Zeroes and Nulls" chapter
Added/revised discussion of /dev/zero.
12) In the "Shell Wrappers" section of "Miscellany" chapter:
Added footnote giving examples of system utilities that are really
shell wrappers.
Added "logging-wrapper.sh" example.
13) In "Indirect References to Variables" section of "Variables Revisited" chapter:
Expanded Nils Radtke's example of building dynamic variable names.
14) In "Parameter Substitution" section of "Variables Revisited" chapter:
Fixed up "ex6.sh" example to make it less ambiguous,
per suggestion of "Der Schwadde" . . . ).
15) In "Miscellaneous Commands" section of "External Commands" Chapter:
At "dd" entry," added lowercase conversion in-line example.
At "jot/seq" entry, added "letter-count.sh" example script.
(Thanks, Stefano Palmeri.)
16) In "System and Administrative Commands" chapter:
At "lockfile" entry, fixed typo in inline example.
(Thanks, Andreas Abraham.)
At "fuser" entry, added more material.
17) In "Gotchas" chapter:
At "Mixing up '=' and '-eq' entry, fixed typo.
(Thanks, Andreas Abraham.)
18) In "Colorizing Scripts" section of "Miscellany" chapter:
Added "horserace.sh" example.
(Thanks, Stefano Palmeri.)
19) In "Redirecting Code Blocks" section of "I/O Redirection" chapter:
Added code snippet and commentary to redir2.sh example.
(Thank you, Bruno de Oliveira Schneider.)
20) In "Copyright" chapter:
Added second URL for French translation.
21) In the "Sed and Awk Micro-primer" appendix:
Fixed "letter-count.sh" example to work with gawk, ver. 3.1.3.
(Thanks to Stefano Palmeri for pointing out the need for a fixup.)
Renamed filename to "letter-count2.sh" to accommodate alternate
version of script which will appear prior to this one in the text.
22) In "Contributed Scripts" appendix:
Fixups to "wgetter2.bash" script.
Added "bashpodder.sh" script.
(Thank you, Linc Fessenden.)
23) In "Writing Scripts" section of "Exercises" appendix:
In "Intermediate sub-section":
Added "Enforcing Disk Quotas" exercise.
24) Various miscellaneous fixups and enhancements:
In example scripts.
In citations of book titles (inserted <citetitle> tag).
Version 3.2
Blueberry release, 02/06/05

View File

@ -52,4 +52,5 @@ dev-tcp.sh (line 14)
archiveweblogs.sh (comment in line 4)
multiple-processes.sh (line 61)
directory-info.sh (lines 36 and 166)
catscripts.sh (lines 12 and 21)
is_spammer.bash (comments on various lines)

File diff suppressed because it is too large Load Diff

View File

@ -23,13 +23,13 @@ echo -n "$n "
: $[ n = $n + 1 ]
# ":" necessary because otherwise Bash attempts
#+ to interpret "$[ n = $n + 1 ]" as a command.
# Works even if "n" was initialized as a string.
# Works even if "n" was initialized as a string.
echo -n "$n "
n=$[ $n + 1 ]
# Works even if "n" was initialized as a string.
#* Avoid this type of construct, since it is obsolete and nonportable.
# Thanks, Stephane Chazelas.
# Thanks, Stephane Chazelas.
echo -n "$n "
# Now for C-style increment operators.

View File

@ -27,6 +27,7 @@ echo "Exit status of \"(( 1 / 2 ))\" is $?." # Rounded off to 0.
# 1
(( 1 / 0 )) 2>/dev/null # Illegal division by 0.
# ^^^^^^^^^^^
echo "Exit status of \"(( 1 / 0 ))\" is $?." # 1
# What effect does the "2>/dev/null" have?

View File

@ -76,7 +76,8 @@ exit 0
# The file cannot not be "undeleted" or retrieved by normal methods.
# However . . .
#+ this simple method would *not* likely withstand forensic analysis.
#+ this simple method would *not* likely withstand
#+ sophisticated forensic analysis.
# This script may not play well with a journaled file system.
# Exercise: Fix it so it does.
@ -90,4 +91,4 @@ exit 0
# For an in-depth analysis on the topic of file deletion and security,
#+ see Peter Gutmann's paper,
#+ "Secure Deletion of Data From Magnetic and Solid-State Memory".
# http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
# http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html

View File

@ -1,26 +1,26 @@
#!/bin/bash
# cannon.sh: Approximating PI by firing cannonballs.
# This is a very simple instance of a "Monte Carlo" simulation,
# This is a very simple instance of a "Monte Carlo" simulation:
#+ a mathematical model of a real-life event,
#+ using pseudorandom numbers to emulate random chance.
# Consider a perfectly square plot of land, 10000 units on a side.
# This land has a perfectly circular lake in its center,
#+ with a diameter of 10000 units.
# The plot is actually all water, except for the four corners.
# The plot is actually mostly water, except for land in the four corners.
# (Think of it as a square with an inscribed circle.)
#
# Let us fire iron cannonballs from an old-style cannon
#+ at the square of land.
# All the shots impact somewhere on the plot of land,
# We will fire iron cannonballs from an old-style cannon
#+ at the square.
# All the shots impact somewhere on the square,
#+ either in the lake or on the dry corners.
# Since the lake takes up most of the land area,
# Since the lake takes up most of the area,
#+ most of the shots will SPLASH! into the water.
# Just a few shots will THUD! into solid ground
#+ in the four corners of the land.
#+ in the four corners of the square.
#
# If we take enough random, unaimed shots at the plot of land,
# If we take enough random, unaimed shots at the square,
#+ Then the ratio of SPLASHES to total shots will approximate
#+ the value of PI/4.
#
@ -32,10 +32,10 @@
# Theoretically, the more shots taken, the better the fit.
# However, a shell script, as opposed to a compiled language
#+ with floating-point math built in, requires a few compromises.
# This tends to lower the accuracy of the simulation, unfortunately.
# This tends to lower the accuracy of the simulation, of course.
DIMENSION=10000 # Length of each side of the plot of land.
DIMENSION=10000 # Length of each side of the plot.
# Also sets ceiling for random integers generated.
MAXSHOTS=1000 # Fire this many shots.
@ -86,8 +86,8 @@ do
printf "Xc = %4d " $xCoord
printf "Yc = %4d " $yCoord
printf "Distance = %5d " $distance # Distance from
#+ center of lake,
# the "origin,"
#+ center of lake --
# the "origin" --
#+ coordinate (0,0).
if [ "$distance" -le "$DIMENSION" ]

View File

@ -17,7 +17,7 @@ column_number=$2
# Passing shell variables to the awk part of the script is a bit tricky.
# See the awk documentation for more details.
# A multi-line awk script is invoked by awk ' ..... '
# A multi-line awk script is invoked by: awk ' ..... '
# Begin awk script.
@ -36,7 +36,7 @@ END {
# It may not be safe to pass shell variables to an embedded awk script,
# so Stephane Chazelas proposes the following alternative:
#+ so Stephane Chazelas proposes the following alternative:
# ---------------------------------------
# awk -v column_number="$column_number" '
# { total += $column_number

View File

@ -9,7 +9,7 @@ b=5
# Bash permits integer operations and comparisons on variables
#+ whose value consists of all-integer characters.
# Caution advised.
# Caution advised, however.
echo

View File

@ -1,13 +1,14 @@
#!/bin/bash
# zmore
#View gzipped files with 'most'
#View gzipped files with 'more'
NOARGS=65
NOTFOUND=66
NOTGZIP=67
if [ $# -eq 0 ] # same effect as: if [ -z "$1" ]
# $1 can exist, but be empty: zmost "" arg2 arg3
# $1 can exist, but be empty: zmore "" arg2 arg3
then
echo "Usage: `basename $0` filename" >&2
# Error message to stderr.
@ -31,11 +32,10 @@ then
exit $NOTGZIP
fi
zcat $1 | most
zcat $1 | more
# Uses the file viewer 'most' (similar to 'less').
# Later versions of 'most' have file decompression capabilities.
# May substitute 'more' or 'less', if desired.
# Uses the filter 'more.'
# May substitute 'less', if desired.
exit $? # Script returns exit status of pipe.

View File

@ -9,10 +9,10 @@ echo $b
a=`echo Hello!` # Assigns result of 'echo' command to 'a'
echo $a
# Note that using an exclamation mark (!) in command substitution
#+ will not work from the command line,
# Note that including an exclamation mark (!) within a
#+ command substitution construct #+ will not work from the command line,
#+ since this triggers the Bash "history mechanism."
# Within a script, however, the history functions are disabled.
# Inside a script, however, the history functions are disabled.
a=`ls -l` # Assigns result of 'ls -l' command to 'a'
echo $a # Unquoted, however, removes tabs and newlines.

View File

@ -6,7 +6,7 @@
# Run as root, of course.
# Insert code here to print error message and exit if not root.
LOG_DIR=var/log
LOG_DIR=/var/log
# Variables are better than hard-coded values.
cd $LOG_DIR

View File

@ -1,4 +1,5 @@
#!/bin/bash
# Faxing (must have 'fax' installed).
EXPECTED_ARGS=2
E_BADARGS=65

View File

@ -16,12 +16,13 @@ esac # Allows ranges of characters in [square brackets],
#+ the tests for lowercase and uppercase characters were
#+ [a-z] and [A-Z].
# This no longer works in certain locales and/or Linux distros.
# POSIX is more portable.
# Thanks to Frank Wang for pointing this out.
# Exercise:
# --------
# As the script stands, it accepts a single keystroke, then terminates.
# Change the script so it accepts continuous input,
# Change the script so it accepts repeated input,
#+ reports on each keystroke, and terminates only when "X" is hit.
# Hint: enclose everything in a "while" loop.

View File

@ -40,7 +40,7 @@ case "$person" in
echo "(212) 533-2814"
echo "(212) 533-9972 fax"
echo "milliej@loisaida.com"
echo "Girlfriend"
echo "Ex-girlfriend"
echo "Birthday: Feb. 11"
;;
@ -59,7 +59,7 @@ echo
# Exercise:
# --------
# Change the script so it accepts continuous input,
# Change the script so it accepts multiple inputs,
#+ instead of terminating after displaying just one address.
exit 0

View File

@ -1,4 +1,5 @@
#!/bin/bash
# "Reading" variables.
echo -n "Enter the value of variable 'var1': "
# The -n option to echo suppresses newline.

View File

@ -11,7 +11,7 @@ $killppp # This variable is now a command.
# The following operations must be done as root user.
chmod 666 /dev/ttyS3 # Must be read+write permissions, or else what?
chmod 666 /dev/ttyS3 # Restore read+write permissions, or else what?
# Since doing a SIGKILL on ppp changed the permissions on the serial port,
#+ we restore permissions to previous state.
@ -24,3 +24,5 @@ exit 0
# 1) Have script check whether root user is invoking it.
# 2) Do a check on whether the process to be killed
#+ is actually running before attempting to kill it.
# 3) Write an alternate version of this script based on 'fuser':
#+ if [ fuser -s /dev/modem ]; then . . .

View File

@ -13,9 +13,9 @@ echo
printf "Pi to 9 decimal places = %1.9f" $PI # It even rounds off correctly.
printf "\n" # Prints a line feed,
# equivalent to 'echo'.
# Equivalent to 'echo' . . .
printf "Constant = \t%d\n" $DecimalConstant # Inserts tab (\t)
printf "Constant = \t%d\n" $DecimalConstant # Inserts tab (\t).
printf "%s %s \n" $Message1 $Message2
@ -34,6 +34,7 @@ Msg=`printf "%s %s \n" $Message1 $Message2`
echo $Msg; echo $Msg
# As it happens, the 'sprintf' function can now be accessed
#+ as a loadable module to Bash, but this is not portable.
#+ as a loadable module to Bash,
#+ but this is not portable.
exit 0

View File

@ -1,6 +1,5 @@
#!/bin/bash
# badname.sh
# Delete filenames in current directory containing bad characters.
for filename in *

View File

@ -36,7 +36,7 @@ echo
#+ then the script terminates with an error message.
# You can specify the error message.
# : ${ZZXy23AB?"ZZXy23AB has not been set."}
# : ${variablename?"ERROR MESSAGE"}
# Same result with: dummy_variable=${ZZXy23AB?}
@ -53,3 +53,5 @@ echo "You will not see this message, because script already terminated."
HERE=0
exit $HERE # Will NOT exit here.
# In fact, this script will return an exit status (echo $?) of 1.

View File

@ -9,14 +9,14 @@
LOWER_LIMIT=1 # Starting with 1.
UPPER_LIMIT=1000 # Up to 1000.
# (You may set this higher... if you have time on your hands.)
# (You may set this higher . . . if you have time on your hands.)
PRIME=1
NON_PRIME=0
let SPLIT=UPPER_LIMIT/2
# Optimization:
# Need to test numbers only halfway to upper limit.
# Need to test numbers only halfway to upper limit (why?).
declare -a Primes
@ -104,8 +104,8 @@ exit 0
# ----------------------------------------------- #
# Code below line will not execute.
# -------------------------------------------------------- #
# Code below line will not execute, because of 'exit.'
# This improved version of the Sieve, by Stephane Chazelas,
#+ executes somewhat faster.

View File

@ -22,6 +22,7 @@ echo "Value of t changed to ${!t}" # 387
# This is useful for referencing members of an array or table,
#+ or for simulating a multi-dimensional array.
# An indexing option would have been nice (sigh).
# An indexing option (analogous to pointer arithmetic)
#+ would have been nice. Sigh.
exit 0

View File

@ -1,5 +1,4 @@
#!/bin/bash
# May need to be invoked with #!/bin/bash2 on older machines.
# Cards:
# Deals four random hands from a deck of cards.
@ -17,7 +16,7 @@ CARDS=52
declare -a Deck
declare -a Suits
declare -a Cards
# It would have been easier and more intuitive
# It would have been easier to implement and more intuitive
#+ with a single, 3-dimensional array.
# Perhaps a future version of Bash will support multidimensional arrays.
@ -77,6 +76,8 @@ seed_random () # Seed random number generator.
seed=`eval date +%s`
let "seed %= 32766"
RANDOM=$seed
# What are some other methods
#+ of seeding the random number generator?
}
deal_cards ()

View File

@ -7,11 +7,14 @@ hello=$a
#-------------------------------------------------------------------------
# No space permitted on either side of = sign when initializing variables.
# What happens if there is a space?
# If "VARIABLE =value",
# ^
#+ script tries to run "VARIABLE" command with one argument, "=value".
# If "VARIABLE= value",
# ^
#+ script tries to run "value" command with
#+ the environmental variable "VARIABLE" set to "".
#-------------------------------------------------------------------------
@ -31,11 +34,13 @@ hello="A B C D"
echo $hello # A B C D
echo "$hello" # A B C D
# As you see, echo $hello and echo "$hello" give different results.
# ^ ^
# Quoting a variable preserves whitespace.
echo
echo '$hello' # $hello
# ^ ^
# Variable referencing disabled by single quotes,
#+ which causes the "$" to be interpreted literally.
@ -64,16 +69,18 @@ echo "var1=$var1 var2=$var2 var3=$var3"
echo; echo
numbers="one two three"
# ^ ^
other_numbers="1 2 3"
# If whitespace within a variable, then quotes necessary.
# ^ ^
# If there is whitespace within a variable, then quotes are necessary.
echo "numbers = $numbers"
echo "other_numbers = $other_numbers" # other_numbers = 1 2 3
echo
echo "uninitialized_variable = $uninitialized_variable"
# Uninitialized variable has null value (no value at all).
uninitialized_variable= # Declaring, but not initializing it
#+ (same as setting it to a null value, as above).
uninitialized_variable= # Declaring, but not initializing it --
#+ same as setting it to a null value, as above.
echo "uninitialized_variable = $uninitialized_variable"
# It still has a null value.
@ -81,7 +88,6 @@ uninitialized_variable=23 # Set it.
unset uninitialized_variable # Unset it.
echo "uninitialized_variable = $uninitialized_variable"
# It still has a null value.
echo
exit 0

View File

@ -1,6 +1,7 @@
#!/bin/bash
# hexconvert.sh: Convert a decimal number to hexadecimal.
E_NOARGS=65 # Command-line arg missing.
BASE=16 # Hexadecimal.
if [ -z "$1" ]

View File

@ -16,6 +16,7 @@ AWKSCRIPT=' { printf( "%3.7f\n", sqrt($1*$1 + $2*$2) ) } '
# command(s) / parameters passed to awk
# Now, pipe the parameters to awk.
echo -n "Hypotenuse of $1 and $2 = "
echo $1 $2 | awk "$AWKSCRIPT"

View File

@ -21,7 +21,7 @@
# ^^^^^^^^^^^
# Or the domain.name(s) from any e-mail address:
# Really_Good_Offer@spammer.biz
# ^^^^^^^^^^^
#
# as the only argument to this script.
#(PS: have your Inet connection running)
#

View File

@ -1,9 +1,9 @@
#!/bin/bash
# keypress.sh: Detect a user keypress ("hot keyboard").
# keypress.sh: Detect a user keypress ("hot keys").
echo
old_tty_settings=$(stty -g) # Save old settings.
old_tty_settings=$(stty -g) # Save old settings (why?).
stty -icanon
Keypress=$(head -c1) # or $(dd bs=1 count=1 2> /dev/null)
# on non-GNU systems

View File

@ -5,14 +5,17 @@ E_NO_ARGS=65
if [ $# -eq 0 ] # Must have command-line args to demo script.
then
echo "Invoke this script with one or more command-line arguments."
echo "Please invoke this script with one or more command-line arguments."
exit $E_NO_ARGS
fi
var01=abcdEFGH28ij
echo "var01 = ${var01}"
echo "Length of var01 = ${#var01}"
# Now, let's try embedding a space.
var02="abcd EFGH28ij"
echo "var02 = ${var02}"
echo "Length of var02 = ${#var02}"
echo "Number of command-line arguments passed to script = ${#@}"
echo "Number of command-line arguments passed to script = ${#*}"

View File

@ -1,60 +1,55 @@
#! /bin/sh
#!/bin/bash
# letter-count.sh: Counting letter occurrences in a text file.
#
# Script by nyal (nyal@voila.fr).
# Used with permission.
# Recommented by document author.
# Written by Stefano Palmeri.
# Used in ABS Guide with permission.
# Slightly modified by document author.
MINARGS=2 # Script requires at least two arguments.
E_BADARGS=65
FILE=$1
let LETTERS=$#-1 # How many letters specified (as command-line args).
# (Subtract 1 from number of command line args.)
INIT_TAB_AWK=""
# Parameter to initialize awk script.
count_case=0
FILE_PARSE=$1
E_PARAMERR=65
usage()
{
echo "Usage: letter-count.sh file letters" 2>&1
# For example: ./letter-count.sh filename.txt a b c
exit $E_PARAMERR # Not enough arguments passed to script.
show_help(){
echo
echo Usage: `basename $0` file letters
echo Note: `basename $0` arguments are case sensitive.
echo Example: `basename $0` foobar.txt G n U L i N U x.
echo
}
if [ ! -f "$1" ] ; then
echo "$1: No such file." 2>&1
usage # Print usage message and exit.
fi
# Checks number of arguments.
if [ $# -lt $MINARGS ]; then
echo
echo "Not enough arguments."
echo
show_help
exit $E_BADARGS
fi
if [ -z "$2" ] ; then
echo "$2: No letters specified." 2>&1
usage
fi
shift # Letters specified.
for letter in `echo $@` # For each one . . .
do
INIT_TAB_AWK="$INIT_TAB_AWK tab_search[${count_case}] = \"$letter\"; final_tab[${count_case}] = 0; "
# Pass as parameter to awk script below.
count_case=`expr $count_case + 1`
# Checks if file exists.
if [ ! -f $FILE ]; then
echo "File \"$FILE\" does not exist."
exit $E_BADARGS
fi
# Counts letter occurrences .
for n in `seq $LETTERS`; do
shift
if [[ `echo -n "$1" | wc -c` -eq 1 ]]; then # Checks arg.
echo "$1" -\> `cat $FILE | tr -cd "$1" | wc -c` # Counting.
else
echo "$1 is not a single char."
fi
done
# DEBUG:
# echo $INIT_TAB_AWK;
cat $FILE_PARSE |
# Pipe the target file to the following awk script.
# --------------------------------------------------------------------------------
awk -v tab_search=0 -v final_tab=0 -v tab=0 -v nb_letter=0 -v chara=0 -v chara2=0 \
"BEGIN { $INIT_TAB_AWK } \
{ split(\$0, tab, \"\"); \
for (chara in tab) \
{ for (chara2 in tab_search) \
{ if (tab_search[chara2] == tab[chara]) { final_tab[chara2]++ } } } } \
END { for (chara in final_tab) \
{ print tab_search[chara] \" => \" final_tab[chara] } }"
# --------------------------------------------------------------------------------
# Nothing all that complicated, just . . .
#+ for-loops, if-tests, and a couple of specialized functions.
exit $?
# This script has exactly the same functionality as letter-count2.sh,
#+ but executes faster.
# Why?

View File

@ -61,7 +61,7 @@ FALSE=1
ALIVE=0
DEAD=1
avar= # Global; holds current generation.
avar= # Global; holds current generation.
generation=0 # Initialize generation count.
# =================================================================
@ -276,7 +276,7 @@ done
avar=`echo ${array[@]}` # Convert array back to string variable.
display "$avar" # Display it.
echo; echo
echo "Generation $generation -- $alive alive"
echo "Generation $generation - $alive alive"
if [ "$alive" -eq 0 ]
then
@ -312,7 +312,7 @@ echo "======================="
Gen0=`echo ${initial[@]}`
display "$Gen0" # Display only.
echo; echo
echo "Generation $generation -- $alive alive"
echo "Generation $generation - $alive alive"
# -------------------------------------------

View File

@ -1,9 +1,10 @@
#!/bin/bash
# line-number.sh
# This script echoes itself twice to stdout with its lines numbered.
# 'nl' sees this as line 3 since it does not number blank lines.
# 'cat -n' sees the above line as number 5.
# 'nl' sees this as line 4 since it does not number blank lines.
# 'cat -n' sees the above line as number 6.
nl `basename $0`

View File

@ -49,7 +49,7 @@ self.show_birthdate # Sat Mar 17 20:13:33 MST 1973
echo
# typeset -f
# to see the created functions (careful, it scrolls off the page).
# typeset -f
#+ to see the created functions (careful, it scrolls off the page).
exit 0

View File

@ -24,9 +24,9 @@ echo "username2 = ${username2:-`whoami`}"
# Compare to first instance, above.
# =============================================================
#
# Reiterating:
# Once again:
variable=
# variable has been declared, but is set to null.

View File

@ -1,4 +1,5 @@
#!/bin/bash
# redir2.sh
if [ -z "$1" ]
then
@ -23,12 +24,24 @@ done <"$Filename" # Redirects stdin to file $Filename.
echo; echo "$count names read"; echo
exit 0
# Note that in some older shell scripting languages,
#+ the redirected loop would run as a subshell.
# Therefore, $count would return 0, the initialized value outside the loop.
# Bash and ksh avoid starting a subshell whenever possible,
# +so that this script, for example, runs correctly.
#
# Thanks to Heiner Steven for pointing this out.
# Therefore, $count would return 0, the initialized value outside the loop.
# Bash and ksh avoid starting a subshell *whenever possible*,
#+ so that this script, for example, runs correctly.
# (Thanks to Heiner Steven for pointing this out.)
exit 0
# However . . .
# Bash *can* sometimes start a subshell in a *redirected* "while" loop.
abc=hi
echo -e "1\n2\n3" | while read l
do abc="$l"
echo $abc
done
echo $abc
# (Thanks, Bruno de Oliveira Schneider, for demonstrating this
#+ with the above snippet of code.)

View File

@ -32,31 +32,31 @@ head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p'
# Assume output up to "sed" --------> |
# is 0000000 1198195154\n
# sed begins reading characters: 0000000 1198195154\n.
# Here it finds a newline character,
# so it is ready to process the first line (0000000 1198195154).
# It looks at its &lt;range&gt;&lt;action&gt;s. The first and only one is
# sed begins reading characters: 0000000 1198195154\n.
# Here it finds a newline character,
#+ so it is ready to process the first line (0000000 1198195154).
# It looks at its &lt;range&gt;&lt;action&gt;s. The first and only one is
# range action
# 1 s/.* //p
# The line number is in the range, so it executes the action:
# tries to substitute the longest string ending with a space in the line
# ("0000000 ") with nothing (//), and if it succeeds, prints the result
# ("p" is a flag to the "s" command here, this is different from the "p" command).
# The line number is in the range, so it executes the action:
#+ tries to substitute the longest string ending with a space in the line
# ("0000000 ") with nothing (//), and if it succeeds, prints the result
# ("p" is a flag to the "s" command here, this is different from the "p" command).
# sed is now ready to continue reading its input. (Note that before
# continuing, if -n option had not been passed, sed would have printed
# the line once again).
# sed is now ready to continue reading its input. (Note that before
#+ continuing, if -n option had not been passed, sed would have printed
#+ the line once again).
# Now, sed reads the remainder of the characters, and finds the end of the file.
# It is now ready to process its 2nd line (which is also numbered '$' as
# it's the last one).
# It sees it is not matched by any &lt;range&gt;, so its job is done.
# In few word this sed commmand means:
# "On the first line only, remove any character up to the right-most space,
# then print it."
# In few word this sed commmand means:
# "On the first line only, remove any character up to the right-most space,
#+ then print it."
# A better way to do this would have been:
# sed -e 's/.* //;q'
@ -68,13 +68,13 @@ head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p'
# nothing (matches line) s/.* //
# nothing (matches line) q (quit)
# Here, sed only reads its first line of input.
# It performs both actions, and prints the line (substituted) before quitting
# (because of the "q" action) since the "-n" option is not passed.
# Here, sed only reads its first line of input.
# It performs both actions, and prints the line (substituted) before quitting
#+ (because of the "q" action) since the "-n" option is not passed.
# =================================================================== #
# A simpler altenative to the above 1-line script would be:
# An even simpler altenative to the above one-line script would be:
# head -c4 /dev/urandom| od -An -tu4
exit 0

View File

@ -18,3 +18,13 @@ do
done
exit 0
# Exercises:
# ---------
# 1) Modify this script to take as an optional argument
#+ the directory to scan for scripts
#+ (rather than just the current working directory).
#
# 2) As it stands, this script gives "false positives" for
#+ Perl, awk, and other scripting language scripts.
# Correct this.

View File

@ -20,4 +20,7 @@ echo "Temp filename = "$temp_filename""
# sh tempfile-name.sh
# Temp filename = temp.e19ea
# Compare this method of generating "unique" filenames
#+ with the 'date' method in ex51.sh.
exit 0

View File

@ -4,7 +4,7 @@
# Written by Rick Boivie.
# Used with permission.
# This is a revised and simplified version of a script
# by Jordi Sanfeliu (and patched by Ian Kjos).
#+ by Jordi Sanfeliu (and patched by Ian Kjos).
# This script replaces the earlier version used in
#+ previous releases of the Advanced Bash Scripting Guide.
@ -35,8 +35,8 @@ do
echo "+---$dir" # ==> Display horizontal connector symbol...
# ==> and print directory name.
numdirs=`expr $numdirs + 1` # ==> Increment directory count.
if cd "$dir" ; then # ==> If can move to subdirectory...
search `expr $1 + 1` # with recursion ;-)
if cd "$dir" ; then # ==> If can move to subdirectory...
search `expr $1 + 1` # with recursion ;-)
# ==> Function calls itself.
cd ..
fi

View File

@ -1,4 +1,5 @@
#!/bin/bash
# unalias.sh
shopt -s expand_aliases # Enables alias expansion.

View File

@ -101,7 +101,7 @@ echo $newestVar
# Why in the world?
# Setting the contents of a string variable containing character
#+ sequences that have a meaning to Bash is a general problem in
#+ sequences that have a meaning in Bash is a general problem in
#+ script programming.
#
# This problem is now solved in eight lines of code

View File

@ -5,7 +5,7 @@ variable=hello # Initialized.
echo "variable = $variable"
unset variable # Unset.
# Same effect as variable=
# Same effect as: variable=
echo "(unset) variable = $variable" # $variable is null.
exit 0

View File

@ -11,7 +11,7 @@ then
echo "Usage: $0 input-file output-file"
exit $E_FILE_ACCESS
fi # Will exit with same error
#+ even if input file ($1) not specified.
#+ even if input file ($1) not specified (why?).
if [ -z "$2" ]
then

View File

@ -5,6 +5,7 @@
# ==>
# ==> Newer Linux distros (2004 or later) autodetect
# ==> and install USB pen drives, and therefore don't need this script.
# ==> But, it's still instructive.
# This code is free software covered by GNU GPL license version 2 or above.
# Please refer to http://www.gnu.org/ for the full license text.

View File

@ -1,10 +1,11 @@
#!/bin/bash
# viewdata.sh
# Conversion of VIEWDATA.BAT to shell script.
DATAFILE=/home/bozo/datafiles/book-collection.data
ARGNO=1
# @ECHO OFF Command unnecessary here.
# @ECHO OFF Command unnecessary here.
if [ $# -lt "$ARGNO" ] # IF !%1==! GOTO VIEWDATA
then
@ -15,6 +16,6 @@ fi
exit 0 # :EXIT0
# GOTOs, labels, smoke-and-mirrors, and flimflam unnecessary.
# The converted script is short, sweet, and clean,
# which is more than can be said for the original.
# GOTOs, labels, smoke-and-mirrors, and flimflam unnecessary.
# The converted script is short, sweet, and clean,
#+ which is more than can be said for the original.

View File

@ -8,9 +8,9 @@ echo "$var" # '(]\{}$" Doesn't make a difference.
echo
IFS='\'
echo $var # '(] {}$" \ converted to space.
echo $var # '(] {}$" \ converted to space. Why?
echo "$var" # '(]\{}$"
# Examples above supplied by S.C.
# Examples above supplied by Stephane Chazelas.
exit 0

View File

@ -23,6 +23,7 @@
# =======================================================================
# changelog:
# 07/02/2005. Fixups by Little Monster.
# 02/02/2005. Minor additions by Little Monster.
# (See after # +++++++++++ )
# 29/01/2005. Minor stylistic edits and cleanups by author of ABS Guide.
@ -236,50 +237,53 @@ list_func() # Gives the user the option to use the -i option to wget,
#+ and a list of URLs.
{
while [ 1 ]; do
echo "Enter the name of the file containing URL's (press q to change your mind)."
echo "Enter the name of the file containing URL's (press q to change your
mind)."
read urlfile
if [ ! -e $urlfile ] && [ $urlfile != q ]; then
if [ ! -e "$urlfile" ] && [ "$urlfile" != q ]; then
# Look for a file, or the quit option.
echo "That file does not exist!"
elif [ $urlfile = q ]; then # Check quit option.
echo "Not using a URL list."
elif [ "$urlfile" = q ]; then # Check quit option.
echo "Not using a url list."
return
else
echo "Using $urlfile."
echo "If you gave me URL's on the command line, I'll use those first."
echo "using $urlfile."
echo "If you gave me url's on the command line, I'll use those first."
# Report wget standard behaviour to the user.
lister=" -i $urlfile" # This is what we will pass to wget.
lister=" -i $urlfile" # This is what we want to pass to wget.
return
fi
done
}
cookie_func() # Give the user the option to use a different cookie file.
cookie_func() # Give the user the option to use a different cookie file.
{
while [ 1 ]; do
echo "Change the cookies file. Press return if you don't want to change it."
echo "Change the cookies file. Press return if you don't want to change
it."
read Cookies
# NB: this is not the same as Cookie, earlier.
# There is an 's' on the end.
# Bit like chocolate chips.
if [ -z $Cookies ]; then # Escape clause for wusses.
if [ -z "$Cookies" ]; then # Escape clause for wusses.
return
elif [ ! -e $Cookies ]; then
echo "File does not exist. Try again." # Keep 'em going . . .
elif [ ! -e "$Cookies" ]; then
echo "File does not exist. Try again." # Keep em going . . .
else
CookiesON=" --load-cookies $Cookies" # File is good. Let's use it!
CookiesON=" --load-cookies $Cookies" # File is good -- let's use it!
return
fi
done
}
run_func()
{
if [ -z "$OPTARG" ]; then
# Test to see if we used the in-line option or the query one.
if [ ! -d "$savePath" ]; then # In case directory doesn't exist . . .
if [ ! -d "$savePath" ]; then # In case directory doesn't exist . . .
echo "$savePath does not appear to exist."
echo "Please supply path and filename of saved wget commands:"
read newFile
@ -289,6 +293,7 @@ if [ -z "$OPTARG" ]; then
read newFile
done
# -------------------------------------------------------------------------
# if [ -z ( grep wget ${newfile} ) ]; then
# Assume they haven't got the right file and bail out.
@ -301,6 +306,7 @@ if [ -z "$OPTARG" ]; then
# If anyone wants to fix it, feel free!
# -------------------------------------------------------------------------
filePath="${newFile}"
else
echo "Save path is $savePath"
@ -358,7 +364,7 @@ done
shift $((OPTIND - 1)) # Do funky magic stuff with $#.
if [ -z "$1" ] && [ ! -z $lister ]; then
if [ -z "$1" ] && [ -z "$lister" ]; then
# We should be left with at least one URL
#+ on the command line, unless a list is
#+ being used -- catch empty CL's.

View File

@ -11,6 +11,7 @@ do
done
exit 0
# You may wish to redirect output of this script, like so:
# ./what.sh >>whatis.db
# or view it a page at a time on stdout,