Documenting Your Script

#
# This is a comment.
#
# Use comments frequently.
# Comments are your friends.

Embedding Documentation in Shell Scripts

#!/usr/bin/env bash
# cookbook filename: embedded_documentation
echo 'Shell script code goes here'
# Use a : NOOP and here document to embed documentation,
: <<'END_OF_DOCS'
Embedded documentation such as Perl's Plain Old Documentation (POD),
or even plain text here.
END_OF_DOCS

Promoting Script Readability

  • Document your script as noted in “Documenting Your Script” and “Embedding Documentation in Shell Scripts”
  • Indent and use vertical whitespace wisely
  • Use meaningful variable names
  • Use functions, and give them meaningful names
  • Break lines at meaningful places at less than 76 characters or so
  • Put the most meaningful bits to the left

Exporting Variables

export MYVAR
export NAME=value

Seeing All Variable Values

Use the env (or export -p) command

Using Parameters in a Shell Script

# simple shell script
echo $1

$ cat simplest.sh
# simple shell script
echo ${1}
$ ./simplest.sh you see what I mean
you
$ ./simplest.sh one more time
one
$ cat tricky.sh
echo $1 $10 ${10}
$ ./tricky.sh I II III IV V VI VII VIII IX X XI
I I0 X

Looping Over Arguments Passed to a Script

#!/usr/bin/env bash
# cookbook filename: chmod_all.1
#
# change permissions on a bunch of files
#
for FN in $*
do
echo changing $FN
chmod 0750 $FN
done

Handling Parameters with Blanks

$ cat quoted.sh
# note the quotes
ls -l "${1}"
$
$ ./quoted.sh "Oh the Waste"
-rw-r--r-- 1 smith users 28470 2007-01-11 19:22 Oh the Waste

Handling Lists of Parameters with Blanks

#!/usr/bin/env bash
# cookbook filename: chmod_all.2
#
# change permissions on a bunch of files
# with better quoting in case of filenames with blanks
#
for FN in "$@"
do
chmod 0750 "$FN"
done

Counting Arguments

#!/usr/bin/env bash
# cookbook filename: check_arg_count
#
# Check for the correct # of arguments:
# Use this syntax or use: if [ $# -lt 3 ]
if (( $# < 3 ))
then
    printf "%b" "Error. Not enough arguments.\n" >&2
    printf "%b" "usage: myscript file1 op file2\n" >&2
    exit 1
elif (( $# > 3 ))
then
    printf "%b" "Error. Too many arguments.\n" >&2
    printf "%b" "usage: myscript file1 op file2\n" >&2
    exit 2
else
    printf "%b" "Argument count correct. Proceeding...\n"
fi

Consuming Arguments

#!/usr/bin/env bash
# cookbook filename: use_up_option
#
# use and consume an option
#
# parse the optional argument
VERBOSE=0;
if [[ $1 = -v ]]
then
    VERBOSE=1;
    shift;
fi
#
# the real work is here
#
for FN in "$@"
do
    if (( VERBOSE == 0 ))
    then
        echo changing $FN
    fi
    chmod 0750 "$FN"
done

Getting Default Values

FILEDIR=${1:-"/tmp"}
$ echo ${HOME:=/tmp}
/home/uid002
$ unset HOME # generally not wise to do
$ echo ${HOME:=/tmp}
/tmp

Using More Than Just a Constant String for Default

cd ${BASE:="$(pwd)"}

Giving an Error Message for Unset Parameters

FILEDIR=${1:?"Error. You must supply a scratch directory."}

Changing Pieces of a String

#!/usr/bin/env bash
# cookbook filename: suffixer
#
# rename files that end in .bad to be .bash
for FN in *.bad
do
    mv "${FN}" "${FN%bad}bash"
done

Using Array Variables

MYRA=(first second third home)
echo runners on ${MYRA[0]} and ${MYRA[2]}
runners on first and third