\input{configpres}

\title{Introduction to Shell Programming}
\maketitle

\begin{frame}
\frametitle{Components of a Script}
\begin{itemize}
\item syntax: "\#!/some/interpreter"
\pause
\item any program can be specified as the interpreter
\pause
\item example: "\#!/bin/sh"
\pause
\item followed by shell commands (for a shell interpreter)
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Hello World as Shell Script}
\begin{lstlisting}
#!/bin/sh

echo 'Hello, world!'
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Variables}
\begin{lstlisting}
#!/bin/sh

# VAR1 defined for this process
VAR1=abc

# set export property of VAR1 for this process
# (now VAR1 is defined for future children processes)
export VAR1

# VAR2 defined only for /bin/sh child process
# (with export property set)
VAR2=def /bin/sh

# clear export property of VAR1 for this process
export -n VAR1

# undefine VAR1 for this process
unset VAR1
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Variables}
\begin{lstlisting}
#!/bin/sh

VAR1=abc
VAR1="a b c"

echo $VAR1
echo ${VAR1}
echo "${VAR1}"
echo '${VAR1}'

VAR1=`date`
VAR1=$(date)
\end{lstlisting}
\end{frame}

\begin{frame}
\frametitle{Special Variables}
\begin{description}
\item[\$0] argv[0]
\item[\$1] argv[1]
\item[\$2] argv[2]
\item[\$\#] argc
\item[\$@] all arguments together as a string
\item[\$\$] my PID
\item[\$?] return value of most recent executed command
\end{description}
\end{frame}

\begin{frame}[fragile]
\frametitle{Example Script}
\begin{lstlisting}
#!/bin/sh

MY_VAR=17
PAR_1=$1
now=`date`

echo variable is ${MYVAR}, parameter is ${PAR_1}
echo date is $now
echo hostname of this machine is $(hostname)
echo 
\end{lstlisting}

\end{frame}

\begin{frame}[fragile]
\frametitle{Output Redirection}
\begin{lstlisting}
#!/bin/sh

# How many lines in addr.txt contain "Jones" ?
# Store the result in "jones_count"
grep Jones addr.txt | wc -l > jones_count

# Append a message to a log file
echo "My message" >> log_file
\end{lstlisting}

\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

if [ condition ]
then
    ...
else
    ...
fi

# in one line...

if [ condition ]; then ...; else ...; fi
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

# number tests: -eq -ne -lt -gt -le -ge
num=15
if [ $num -lt 20 ]; then ...; fi

# string tests: = != < > -n -z
string="Hello"
if [ $string != "hello" ]; then ...; fi
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

# file tests:
# -f is a normal file
# -d is a directory
# -e exists
# -s exists and is not empty
# -r is readable
# -w is writable
# -x is executable
# -b is a block device
# -c is a character device
filename="myfile"
if [ -f $filename ]; then ...; fi
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

# all tests can be negated with '!'
filename="myfile"
if [ ! -f $filename ]; then ...; fi

# tests can be combined with a logical and '-a' and or '-o'
filename="myfile"
num=15
string="Hello"
if [ -f $filename -o ! $num -lt 20 -a $string != "hello" ]; then ...; fi
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

# Does addr.txt contain "Jones" ?
if grep Jones addr.txt; then ...

# Return value 0 means OK
exit 0

\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

VAR=abcdef

case $VAR in
abc)
    echo "exactly abc"
    ;;
abcdef)
    echo "exactly abcdef"
    ;;
abc*)
    echo "begins with abc"
    ;;
*)
    echo "match everything"
    ;;
esac

\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Conditional Branching}
\begin{lstlisting}
#!/bin/sh

# short circuit tests:

make && make install

grep Jones addr.txt || echo "No Jones found!"

\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Loops}
\begin{lstlisting}
#!/bin/sh

for filename in file1 file2 file3
do
    cp $filename $filename.bak
done

for filename in *
do
    ...
done
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Loops}
\begin{lstlisting}
#!/bin/sh

while [ condition ]
do
    ...
done

while [ condition ]; do ...; done

# "while conditions" are the same as "if conditions"
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Functions}
\begin{lstlisting}
#!/bin/sh

error_log() {
    echo "Error: $1" >> my_log_file
}

...

error_log "file not found"
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Using External Scripts}
\begin{lstlisting}
#!/bin/sh

# include an external script
. /path/to/my_other_script

# run an external script
/path/to/my_other_script
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Accessing Files}
\begin{lstlisting}
#!/bin/sh

ls -1 > filelist.txt

while read filename
do
    if [ -d $filename ]
    then
        echo "$filename is a directory"
    fi
done < filelist.txt
\end{lstlisting}
\end{frame}

\input{tailpres}
