Standardizing Scripts
http://mirror.aarnet.edu.au/linux/LDP/HOWTO/Adv-Bash-Scr-HOWTO/index.html

Notes:

Bash v2 scripting uses strings differently. Within your comparison
statements with strings, use an x or something instead of making it a
blank or stand-alone string. An example follows:

	if [ "x$pf" != x"NO" ]; then
	if [ x"${ipfilter}" = x"YES" -a -f "${ipfilter_rules}" ]; then

Redirects:

	1>  filename    - redirects STDOUT to filename (erases file contents)
	 >  filename

	1>> filename    - redirects STDOUT to filename (appends to file)
	 >> filename

	2>  filename    - redirects STDERR to filename

	1>&2            - redirects output to STDERR
	>&2

	2>&1            - redirects STDERR to STDOUT
			  The '&' redirects to the number following it.

	< filename      - inputs filename contents to a command:
			  cat filename or cat < filename

	>|              - Force Redirection, forcibly overwrites an existing
			  file even if 'noclobber env variable is in effect.

	-               - Redirection from/to STDIN or STDOUT
			  This option is not an option of sh but an option
			  of utilities to alias a filename with STDOUT.

-----------------------------------------------------------------------------

Script Variables:

	$0	- The filename of the script.
	$1	- The first command line argument.
	$n	- The (n)th command line argument.
	$@	- Array of command line arguments (quoted / not expanded).
	$#	- The number (integer) of command line arguments.
	$*	- List of command line arguments.
	$$	- The Process ID (PID) of the script.
	$?	- Exit status of last command, function, or script.
	$-	- Flags passed to script.
	$!	- PID of last job run in background (job &).

	ls | grep "file_name.ext"
	if [ ! "$?" = "0" ]; then
		echo "file_name.ext not found"
	fi

	/sbin/pidof pppd >/dev/null 2>&1; PPPDQ="$?"
	if [ "$PPPDQ" = "0" ]; then
		killall pppd
	fi

-----------------------------------------------------------------------------

Environment Variables:

	$FILE=
	$FILE="/bin/sh"
	echo $FILE

	$NUM=
	$NUM=1
	$NUM=`expr $NUM + 1`

-----------------------------------------------------------------------------

Using /bin/echo:

	To use the output of a command:
		echo "This system is: `uname -a`"

	To echo data but not a carriage return, use the -n switch:
		echo -n "No line return after this!"

	To ring the system bell, use the -e switch:
		echo -e "\a"

	The -e switch has makes echo interpret escape sequences
	such as \n \t \a \\, etc. For more help on this:
		% man echo

-----------------------------------------------------------------------------

Statements:

	The opening bracket '[', is an alias for test, in theory, it is
	not necessary for the closing bracket ']' but newer versions of
	bash will complain if it is omitted.

	if [ -f /bin/sh ]; then
		echo "You have the /bin/sh shell."
	elif [ -f /bin/bash ]; then
		echo "You have the /bin/bash shell."
	else
		echo "The else statement."
	fi

	if [ ] && [ ]; then
		...
	fi

	if [ ] || [ ]; then
		...
	fi

	[ -f /etc/spcsys ] && echo /etc/spcsys is present.

	[ ! -f /etc/spcsys ] || echo /etc/spcsys is present.

	if [ -f /etc/spcsys1 -o -f /etc/spcsys2 ]; then
		echo "OR is true"
	fi

	if [ -f /etc/spcsys1 -a -f /etc/spcsys2 ]; then
		echo "AND is true"
	fi

	if [ $# = "0" ]; then
		echo "No arguments"
	elif [ $# = 1 ]; then
		echo "1 argument: $1"
	else
		shift		# removes $1 from stack.
		echo "${@-}"	# echoes all other arguments.
	fi

	case ${file} in
		*.gif|*jpg)
			echo "${file}: graphic file"
			;;
		*.txt|*.tex)
			echo "${file}: text file"
			;;
		*)
			echo "${file}: generic file"
			;;
	esac

	case `cat file.ext` in
		*string*)
			echo "It exists"
			;;
		*)
			echo "It does not exist"
			exit 0
			;;
	esac

	case `ping -qnc some.machine.net` in
		*'100% packet loss'*)
			echo "The network is down."
			echo
			exit 0
			;;
	esac

	case `ping -qnc 1 www.yahoo.com` in
		*'100% packet loss'*)
			echo "The network is DOWN."
			echo ""
			exit 1
			;;
		*)
			echo "The network is UP."
			echo ""
			;;
	esac

	# case with regular expressions:
	echo -n "Enter a key and hit enter"; read k
	case "$k" in
		[a-z]) echo "lowercase letter";;
		[A-Z]) echo "Uppercase letter";;
		[0-9]) echo "Number";;
		*    ) echo "Non character";;
	esac


-----------------------------------------------------------------------------

Loops:

	for { variable name } in { list }
	do
		...
	done

	for i in 1 2 3 4 5
	do
		echo "Welcome $i times"
	done

	for NAME in hamish heidi matthew riaan simone
	do
		echo "people involved in this project: "
		echo $NAME
	done

	for file in `ls .` ; do
		echo "${file}"
		...
	done

	for var in /dev/ttyS[1-9]*; do
		echo $var
	done

	# Loop over the command-line arguments:
	# Note: The $* argument will fail if spaces exist.
	for filename in "$@"; do
		echo "$filename"
	done

	# If 'in' is omitted, for works on '$#'
	for i; do
		echo $i
	done

	for (( start value; comparison; count increment ))
	for (( expr1; expr2; expr3 ))
	do
		repeat all statements between do and 
		done until expr2 is TRUE
	done

	for ((  i = 0 ;  i <= 5;  i++  ))
	do
		echo "Welcome $i times"
	done

	for ((i=0; i<=10; i=i+1))	#can replace i=i+1 with i++
	do
		echo $i
	done

	count=1
	for arg
	do
		echo "Argument $count is $arg"
		$((count=count+1))  #or: count=$((count+1))   or:  count=`expr $count + 1`
		: $((count=count+1))   #prevents error message where it is looking to execute the number (: = noop)
	done

	for i in `seq 20`
	do
		echo $i
	done

	---------------------------------------------------------------------

	while [ $i -lt 10 ]; do
		...
		i=`expr $i + 1`
	done

	cat $0 | while read line; do
		echo $line
	done

	---------------------------------------------------------------------

	until [ $i -gt 10 ]; do
		...
		i=$(($i+1))
	done

	---------------------------------------------------------------------

	contine and break
	while [ condition ]; do
		...
		if [ condition ]; then
			continue [or break]
		fi
		...
	done

-----------------------------------------------------------------------------

Pipes:

	To pipe the entire output stream of a set of commands into
	a single application, use '() |'. Example:

		(
			echo "To: hostmaster "
			echo "From: system "
			echo "Subject: Anything"
			...
		) 2>&1 | /usr/lib/sendmail -t

-----------------------------------------------------------------------------

The colon symbol ":" (null command) is an alias for true. For example,
it can be used for an endless loop:

	while : ; do
		...
	done

A colon may also be used as a placeholder in an if/then test:

	if condition
	then : #do nothing and branch ahead
	else
		...
	fi

A colon may be used to evaluate variables using "parameter substitution":

	: ${HOSTNAME?} ${USER?} ${MAIL}
		# prints an error message if one or more not set.

-----------------------------------------------------------------------------

Reading STDIN:

	echo "Are you in a good mood? [y,n]"
	read ans
	if [ "$ans" = y ]; then
		echo "Good!"
	elif [ "$ans" = n ]; then
		echo "Sorry!"
	else
		echo "Error: Bad option"
	fi

-----------------------------------------------------------------------------

Special Characters And Syntax:

	${}	- Parameter Substitution

		To strip off the shortest/longest part of a 'pattern' if it
		matches the front end of 'var':

			${var#pattern} / ${var##pattern}

		To strip off the shortest/longest part of 'pattern' if it
		matches the back end of 'var':

			${var%pattern} / ${var%%pattern}

		Example of renaming file extensions, to rename all .gif
		files to .jpg files:
			# ./script gif jpg
			for filename in *.$1; do
				mv $filename ${filename%$1}$2
			done

		-------------------------------------------------------------

		${var:pos}
			'var' expanded, starting from offset 'pos'.

		${var:pos:len}
			'var' expanded to a max of 'len' characters.

		${var/pattern/replace}
			First match of 'pattern', within 'var' replaced
			with 'replace'. If 'replace' is omitted, the first
			match of 'pattern' is stripped or deleted.

		${var//pattern/replace}
			All matches of 'pattern', within 'var' are replaced
			with 'replace'. If 'replace' is omitted, all matches
			of 'pattern' are stripped or deleted.

	---------------------------------------------------------------------

	/{}	- File Pathname, used mostly in 'find' constructs

	---------------------------------------------------------------------

	()	- Command Group

		Commands enclosed within parentheses starts a subshell.

	---------------------------------------------------------------------

	{}	- Block of Code

		Creates an anoymous function, the code block enclosed
		in braces may have I/O redirected to and from it.

		{
		read fstab
		} < /etc/fstab
		echo "First line in /etc/fstab is:"
		echo $fstab

-----------------------------------------------------------------------------

Bash Internal Commands:

	getopts	- parses command line arguments passed to a script.
	          The argument must be proceeded with either a '-' or
	          a '+'.

		while getopts ":mnopq:rs" option; do
		# the ':' after q shows it will have an option after it.
			case $option in
				m) ... ;;
				q) echo $OPTARG ;;
				...
			esac
		done
		shift $(($OPTIND - 1))
		The

	---------------------------------------------------------------------

	basename
		- strip path from filename.
		basename /bin/ls

	dirname
		- strip basename from filename.
		dirname /bin/ls

	factor
		- factor an integer into prime factors.
		factor 1024

	hash[cmds]
		- Record the path name of specified commands. When
		  hash is called with no arguments, it lists hashed
		  commands.

	wait
		- stop script execution until all background processes
		  finish.

	suspend
		- same as control-z [^z].

	stop
		- same as suspend but for background processes.

	times
		- gives statistics on the system time used in executing
		  commands.
 000000*
-----------------------------------------------------------------------------

Typing Variables: declare or typeset:

	declare [option flag] variable_name

	option flags:

		-r	- readonly
		-i	- integer
		-a	- array
		-f	- functions
			# no arguments will list all functions.
			declare -f
		-x	- export

-----------------------------------------------------------------------------

Arithmetic:

	To perform simple arithmetic, use the 'expr' command.

	x=24
	y=04
	result=$(expr $x \* $y)
	echo "$x times $y is $result"

	let a=16+5
	
	i=1 ; z=10
	while [ $i -le $z ]; do
		echo $RANDOM
		let "i += 1"
	done

-----------------------------------------------------------------------------

Using AWK:

	The AWK command is used to read and print formatted text such
	as tables seperated by whitespace.

	ls -al | awk '{print $5}'

	ls -al | awk '{sum = sum + $5} END {print sum}'

-----------------------------------------------------------------------------

Using sed (Stream Editor):

	The sed utility reads the specified files, or the standard input if
	no files are specified, modifying the input as specified by a list
	of commands. The input is then written to the standard output.

	To remove blank lines in a file:
		sed -e /^$/d filename

	To substitute one pattern for another:
		sed -e "s/old_pattern/new_pattern/" filename