 
  % -------------------------------------------
  %  latex generated by: booktolatex.cgi   
  %   from source file : ../htdocs/books/bash/bash-book.txt       
  %                  on: 20 April 2024,  1:48pm         
  %         querystring: books/bash/bash-book.txt  
  %       document-root: /var/www/html
  %         script-name: /cgi-bin/booktolatex.cgi
  %         Server-name: bumble.sourceforge.net
  %          Sed-script: booktolatex.sed
  % ------------------------------------------- 

  \documentclass[a4paper,12pt]{article} 
  \usepackage[margin=0.4cm,noheadfoot]{geometry} 
  \usepackage{color}                   %% to use colours, use "xcolor" for more
  \usepackage{multicol}                %% for multiple columns 
  \usepackage{keystroke}               %% for keyboard key images 
  \usepackage[toc]{multitoc}           %% for multi column table of contents
  \usepackage{tocloft}                 %% to customize the table of contents
  \setcounter{tocdepth}{2}             %% only display 2 levels in the contents
  \setlength{\cftbeforesecskip}{0cm}   %% make the toc more compact
  \usepackage{listings}                %% for nice code listings
  %\lstset{language={},
  \lstset{language=bash,                 
    %% define special comment delimiters '##(' and ')' 
    moredelim=[s][\color{grey}\itshape\footnotesize\ttfamily]{~(}{)},
    basicstyle=\ttfamily,           %% fixed pitch font
    xleftmargin=1cm,                %% margin on the left outside the frames
    breaklines=true,                %% break long code lines
    breakatwhitespace=false,        %% break long code lines anywhere
    breakindent=10pt,               %% reduce the indent from 20pt to 10
    postbreak=\mbox{{\color{blue}\small$\Rightarrow$\space}},  %% mark with arrow
    showstringspaces=false,            %% dont show spaces within strings 
    framerule=5pt,                     %% thickness of the frames
    rulecolor=\color{lightgrey}, frame=l}   %% source code settings
  \usepackage{graphicx}                %% to include images
  \usepackage{fancybox}                %% boxes with rounded corners 
  \usepackage{wrapfig}                 %% flow text around tables, images 
  \usepackage{tabularx}                %% change width of tables 
  \usepackage[table]{xcolor}           %% alternate row colour tables
  \usepackage{booktabs}                %% for heavier rules in tables 
  \usepackage[small,compact]{titlesec} %% sections more compact, less space
  \usepackage{enumitem}                %% more compact and better lists 
  \setlist{noitemsep}                  %% reduce list item spacing 
  \usepackage{hyperref}     %% make urls into hyperlinks
  \hypersetup{              %% add "pdftex," if only pdf output is required
     colorlinks=true,       %% set up the colours for the hyperlinks 
     linkcolor=black,       %% internal document links black 
     urlcolor=black,        %% url links black 
     filecolor=red,       
     citecolor=red, 
     bookmarks=true, pdfpagemode=UseOutlines} 

  % define some colours to use
  \definecolor{lightgrey}{gray}{0.70}
  \definecolor{grey}{gray}{0.30}

  \titleformat{\section}[frame]    %% titlesec: create framed section headings
     {\normalfont} 
     {\filleft \footnotesize \enspace Section \thesection\enspace\enspace} 
     {3pt} {\bfseries\itshape\filright} 
     
  \title{The Bourne Again Shell} 
  \author{}
  \date{11 August 2020,  3:13pm} 
  \setlength{\parindent}{0pt}
  % \setlength{\parskip}{1ex}

  % label lists with stars
  \renewcommand{\labelitemi}{$\star$}

  \begin{document} 

  \centerline{\Large \bf The Bourne Again Shell} \medskip
  \begin{center}
    {\huge ``}\textit{bash scripts are dyslexic poetry}{\huge ''}
    \textsc{anon}
  \end{center}
  % -----------------------------------
  % the toc should be 2 columns because of the \multitoc package 
  \tableofcontents


 

  The Bourne Again Shell, or 'Bash' shell is one of the ways that a 
  user may interact with the Linux Operating System. The Bash shell
  is extremely flexible and powerful since it has a full range of 
  programming constructs, such as loops and tests as well as the 
  ability to join commands in command chains using the pipe "|"
  symbol.

  The name 'Bourne Again' comes from the fact that the 'bash'
  shell was a rewrite of an earlier unix shell called the 
  'Bourne Shell'.

\section{Getting Help}

\emph{ View help for the built-in bash commands  }
\begin{lstlisting}
  help
\end{lstlisting}

\emph{ View help for the 'pwd' print working directory command }
\begin{lstlisting}
  help pwd
\end{lstlisting}

\emph{ Show all software about optical character recognition or speech }
\begin{lstlisting}
  apropos speech ocr | less
\end{lstlisting}


\begin{center}
  \includegraphics[width=0.4\textwidth]{image/eg-apropos-ocr.png}
\end{center}

  Optical character recognition means software which can 'recognise'
  written characters (letters) which form part of an image and 
  can turn those characters into text.

\emph{ Display a short help message for all programs in the system  }
\begin{lstlisting}
  whatis -r '.*' | less
\end{lstlisting}

\emph{ Show some installed programs having something to do with 'java' }
\begin{lstlisting}
  whatis -r java | less
\end{lstlisting}
\begin{lstlisting}
  apropos -r java | less  
\end{lstlisting}

  Apropos is better than 'whatis' because it actually searches
  the man pages for mentions of the given term, where as 
  'whatis' just looks at the short description of the program

\emph{ Show the version number of the bash shell which you are using  }
\begin{lstlisting}
  echo $BASH_VERSION
\end{lstlisting}

\emph{ Hold down the escape key for a few seconds to see all commands }
\begin{lstlisting}
  ESC  
\end{lstlisting}

\section{Web Links}

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://tldp.org/LDP/abs/html/}]  
      a tutorial
 \item[\url{www.commandlinefu.com}] 
      lots of recipes
 \item[\url{www.shelldorado.com}]
      more bash tips
 \item[\url{http://www.bash-hackers.org/wiki/doku.php}]
      stuff about the bash shell
 \item[\url{http://bashcurescancer.com/10-linux-commands-youve-never-used.html}]
      about little used but useful commands
 \item[\url{www.stackoverflow.com}]
      This is a forum about any programming language, but
      it generally contains intelligent answers to bash
      questions.
 \item[\url{http://www.faqs.org/faqs/unix-faq/shell/bash/}]
      a bash faq
\end{description}

\section{Traps And Gotchas}

  This section details some unpleasant surprises awaiting
  the unwary bash novice.

\emph{ Be careful about white space in bash statements }
\begin{lstlisting}
  d=2 NOT d = 2
\end{lstlisting}
\begin{lstlisting}
  if [ $a -le 5 ] NOT if [ $a -le 5]
\end{lstlisting}

\emph{ There must be a space after a $\{$ bracket }
\begin{lstlisting}
  for j in 1 2 3 4; {echo "j=$j"; }   ~(NO!! doesnt work)
\end{lstlisting}

\emph{ No!!! you need spaces after ``\$a'' and before ``\$b'', for some reason  }
\begin{lstlisting}
  a='ss'; [ "$a"=="$b" ] && echo yes
\end{lstlisting}

\emph{ Scripts with MS Windows newlines \textbackslash r\textbackslash n will not run }
\begin{lstlisting}
  #!/bin/bash\r\n   ~(doesnt work, use the 'dos2unix' tool)
\end{lstlisting}

\emph{ The so called ``back-ticks'' (`) need to be escaped in shell scripts  }
\begin{lstlisting}
  \`\`    ~(the ` character is similar to the '$(...\)' construct)
\end{lstlisting}

\emph{ Echo doesnt show newlines. It removes the newlines from string variables }
\begin{lstlisting}
  s="first "$'\n'"2nd "$'\n'"3rd"; echo $s
\end{lstlisting}

  This prints ``first 2nd 3rd'' all on one line, BUT the variable "s"
  actually spans 3 lines. use 'echo ``\$s''' to actually show the real contents
  of the variable 's' with newline characters
 
\emph{ Cant use bash -v to get the version, use the following instead }
\begin{lstlisting}
  echo $BASH_VERSION
\end{lstlisting}

\emph{ Brace expansion cant have spaces  }
  
\emph{ You cant background a job on the same line with another command  }
\begin{lstlisting}
  ls &; clear   ~(No!! this doesnt work)
\end{lstlisting}
\begin{lstlisting}
  ls &;         ~(No!! also doesnt work)
\end{lstlisting}

\emph{ Just omit the ';' semi-colon, but how does this work? }
\begin{lstlisting}
  ls & clear  
\end{lstlisting}
  
\section{Jargon}

  This section attempts to explain some of the technical terms
  which are often used when describing the bash shell. Many 
  of these terms have a long (more than 30 years) tradition of use
  in Unix-type operating systems.

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{terminal}]
     An rs-232 serial device consisting of a keyboard and screen
     which communicates with a computer, or else software which
     emulates this. 
 \item[\url{console}]
 \item[\url{shell}]
     This is a way of interacting with the operating system
     by typing a series of very cryptic and precise commands.
     Most users have an instinctive dislike and dread of this
     type of activity.
 \item[\url{built-in}] command
     a command which is part of bash (does not need any
     external program to execute). You can view some help for these
     commands by typing 'help command' in a console.
 \item[\url{variable}]
     A variable is an entity which may contain a value
     such as '2' or ``The tree''. The variable can change its
     value as often as is required (this is why its called
     a 'variable')
 \item[\url{untyped}] and typed variables
     variables can contain various values and those values
     can be classified into 'types' such as text (also called
     'strings') whole numbers (also called 'integers') or 
     decimal numbers (also called 'floating point numbers')
     Bash normally uses 'untyped' variables because it does 
     not really care what type of value the variable holds
     (whether the variable is text, an number or something else).
     The bash shell attempts to 'guess' what type of value a
     variable holds, and then tries to do something 'sensible'
     with that value.    
 \item[\url{variable}] interpolation
     This term refers to the process of inserting or substituting
     string (text) variables which are contained within other
     text variables. So if we have s=4; t=``1 2 3 \$s'' then the 
     value of the variable 't' will be '1 2 3 4' because the variable
     's' was 'interpolated' within the variable 't'. This is
     a very handy feature of many modern scripting languages such as
     Perl, Ruby, Python etc
 \item[\url{string}]
     In the world of programming a string refers to a chunk
     of text. This is because 'strings' were first thought
     of as a string of characters.
 \item[\url{BSD}]
     Berkeley Standard Distribution of Unix. This is, more or
     less the version of Unix used with MacOSX and many of
     the standard programs are slightly different to their
     Gnu-Linux equivalents. For this reason, when writing bash
     scripts that need to run on both Mac OSX and Linux, the 
     programmer must be sure to only use posix switches
 \item[\url{FreeBSD}]
     A free version of the BSD Unix operating system. This is 
     not a popular as Linux, but has the reputation for being more
     secure and better for older machines. FreeBSD may be capable
     of running on old 486 machines
 \item[\url{Posix}]
     After the development of BSD Unix, there began to appear
     different versions of Unix which had small but significant
     differences. The Posix standard was an attempt to 'reunify'
     different Unix versions by specifying standards that all
     Unix type operating systems (including Linux) should 
     implement. By conforming to posix standards, one is able to 
     write bash shell scripts which should run correctly on a
     wide variety of different Unix-type systems, such as Mac OSX
     Linux and FreeBSD
 \item[\url{globbing}]
     The bash shell expands certain special characters 
     (such as '*') into a list of file names in the 
     current folder.
 \item[\url{brace}] expansion
     expands an expression containing braces '$\{$$\}$' into a series
     of numbers or files names.
 \item[\url{script}]
     A script is a set of instructions contained within a text
     file in a format which is readable and understandable by a person
     (after some training) which is also readable and executable
     by a computer program in order to carry out some particular
     task.
 \item[\url{backtics}]
     The 'backtic' (`) along with the more modern \$() construct
     is used to insert the output of a command within another
     command or piece of text. It is an extemely powerful technique.
     The more modern \$() may be nested but the older `` may not
 \item[\url{option,}] switch
     These 2 terms which are equivalent are used to alter the behavior
     of the application or script. Options or switches are usually
     written with a hyphen before a letter (for example '-a' or '-b')
     or with 2 hyphen before a word or words (eg: '--list' or '--version')
 \item[\url{short}] option
     The short option to a command is one hyphen followed by one 
     letter (eg: '-a' or '-b')
 \item[\url{long}] option
     an option to a command written with words rather than a single
     letter (eg --debug)
 \item[\url{parameter}]
     Parameters are values which are passed to scripts and 
     functions in order to provide information to the script or 
     function. For example if a script is executed with 
     './test.sh green white' then the first parameter has the 
     value 'green' and the 2nd parameter has the value 'white'
     The parameters can be used within the script by accessing the 
     variables \$1, \$2, ... etc.
 \item[\url{bash}] function
     a function is a way of coding a task that is opten repeated.
     A function is slightly more flexible than an alias, and slightly
     less flexible than a script.
 \item[\url{alias}]
     This is the simplest way to create new commands for tasks which
     you often carry out using the bash shell. Aliases cannot have
     parameters.
 \item[\url{shebang}] line
     The 'shebang' line is the line at the top of a unix script which
     begins with '\#!' and then a path. This line tells the unix or 
     linux operating system what program to use to execute the script
 \item[\url{executable,}] application, program
     All these terms are more or less equivalent and mean a
     file or files containing instructions which a computer
     can carry out in order to perform a particular task
     (such as surf the internet or write a document)
 \item[\url{binary}] file
 \item[\url{text}] file
     A text file represents a series of characters in some human
     writing system. Each character in the writing system
     (such as the chinese ideograph for 'rain' or the roman alphabet
     letter 'z' or the greek 'alpha' character) is given a 
     unique number and is then encoded into a binary code which may
     be stored on a computer system.
 \item[\url{character}]
 \item[\url{text}] encoding
     This is the way that each character in a text file is transformed
     into a unique number (in binary code). Ascii was an old text
     encoding which was used for encoding the roman alphabet. Utf8 
     is a more modern encoding which is capable of encoding any 
     character in any known human writing system.
 \item[\url{Unicode}]
     Unicode is a very useful standard developed over a number of 
     years by a committee to provide a way to categorise and 
     enumerate all the characters in all the writing systems which
     are currently known in the world. This standard makes the job
     of writing text documents which can be used and read over the 
     Internet in different countries, much easier.
 \item[\url{locale}]
     Different human cultures use different writing systems to write
     documents, display numbers in different ways and use different
     languages. For example, in Colombia the number 2.200,33 means '2
     thousand, 2 hundred  and 1/3 (approximately) but in an Anglo-Saxon
     country, the number would be written 2,200.33. Linux attempts to
     cater for these different cultures using 'locales'.  
 \item[\url{interface}]
     The interface is the way that a human being interacts with
     a computer program. This is usually by typing text into small
     boxes, clicking 'buttons', choosing elements from lists and so
     on. An interface could also be based apon voice recognition 
     and sound. In old unix programs the interface consists purely
     of text messages.
 \item[\url{curses}]
     curses is a type of user interface which runs within
     a terminal. It allows the user to use the arrow keys to
     move around the screen. It is essentially a more 
     'primitive' version of graphical windows.
  @@
\end{description}

\section{Other Shells}

  While bash is considered the most popular and widely used
  shell for linux and other unixes, other shells exist.


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ different shells }} \\
  \hline

  \texttt{ csh } & A shell with a c like syntax \\ 

  \texttt{ ksh } & The korn shell  \\ 

  \texttt{ dash } & A 'sh' implementation \\ 

  \texttt{ sh } & An old shell \\ 

  \texttt{ fish } & A simple non-compatible shell \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Find out the name of the running shell or script  }
\begin{lstlisting}
  echo $0
\end{lstlisting}

\section{Processes And Jobs}

  Any unix-style operating system (and most modern operating systems) can
  do more than one thing at once. Each of these tasks is called a 'job' or
  a 'process'. There is a subtle difference but we wont worry about it
  right now.

\emph{ Run the command apropos shell $>$ shell-commands as a background job }
\begin{lstlisting}
  apropos shell > shell-commands & 
\end{lstlisting}

\emph{ Use export to make a variable available to subprocesses }
\begin{lstlisting}
  export name=value
\end{lstlisting}

\emph{ Pause a currently executing job }
\begin{lstlisting}
  [control] z
\end{lstlisting}

\emph{ Show what jobs the shell is executing }
\begin{lstlisting}
  jobs
\end{lstlisting}

\emph{ Stop the second job in the job list }
\begin{lstlisting}
  kill %2  ~(a job number is different from a process number)
\end{lstlisting}
 
\emph{ Stop the process with id '1423'  }
\begin{lstlisting}
  kill -9 1423
\end{lstlisting}

\emph{ Bring a job which is executing in the background to the foreground }
\begin{lstlisting}
  fg  
\end{lstlisting}
  (if there is more than 1 background job, add a job-number)

\emph{ Put into the background a job running in the foreground }
\begin{lstlisting}
  bg
\end{lstlisting}

\emph{ Show all executing processes using 'unix' options }
\begin{lstlisting}
  ps -e
\end{lstlisting}

\emph{ Show the process id and initiating command of all processes }
\begin{lstlisting}
  ps -eo pid,comm
\end{lstlisting}

\emph{ Run a command which will not be interrupted when the user logs out.  }
\begin{lstlisting}
  nohup command
\end{lstlisting}

\emph{ Run a command with a priority less than normal }
\begin{lstlisting}
  nice command
\end{lstlisting}

\emph{ Display a list box of running processes }
\begin{lstlisting}
  echo "$(ps -eo pid,comm | zenity --list --column= --height 800)"
\end{lstlisting}
  
\emph{ Display a list- box of running processes and kill the process chosen }
  \begin{lstlisting}
   p="$(ps -eo pid,comm | zenity --list --column= --height=800)"; kill -9 $(echo $p | sed 's/ .*$//');
  \end{lstlisting}

\section{Text Files}

\emph{ The right way to read a text file }
  \begin{lstlisting}
   cat test.txt | while read l; do
     echo "$l"
   done
  \end{lstlisting}


\emph{ Create a new file 'list' and type text into it }
\begin{lstlisting}
  cat > list -   ~(press [control] + c to stop this)
\end{lstlisting}

\emph{ Read 3 characters from an input stream }
\begin{lstlisting}
  echo abcdef > junk.txt; read -n 3 a <junk.txt; echo $a;   ~(prints "abc")
\end{lstlisting}

\emph{ Loop through the words of a text file }
\begin{lstlisting}
  for i in $(cat example.txt); do echo $i; done
\end{lstlisting}
\begin{lstlisting}
  for i in $(<example.txt); do echo $i; done  ~(the same)
\end{lstlisting}

\emph{ Loop through the lines of a text file }
\begin{lstlisting}
  while read -r a ;do echo $a; done < file.txt
\end{lstlisting}

\emph{ Loop through the characters of a text file }
\begin{lstlisting}
  while read -n 1 a ;do echo $a; done < file.txt
\end{lstlisting}

\emph{ Insert ``yes'' at the 4th character in a text file }
\begin{lstlisting}
  exec 3<> file.txt ; read -n 4 <&3 ; echo -n yes >&3 ; exec 3>&- ;
\end{lstlisting}

\emph{ A very simple text translation script   }
  \begin{lstlisting}
    exec 3< file.txt
    while read a <&3
    do 
      echo -ne "--\n$a\n>>"; read b; echo $b >> file.tr.txt
    done; exec 3<&- 
  \end{lstlisting}

\emph{ A very simple text translation script with line numbers }
  \begin{lstlisting}
    exec 3< test.txt
    n=1
    while read a <&3
    do 
      echo -ne "$n--\n$a\n>>"; read b; echo $b >> eg.tr.txt
      ((n++))
    done; exec 3<&- 
  \end{lstlisting}

\emph{ Create a small amount of random text for filling up documents }
\begin{lstlisting}
  cat /usr/share/dict/words | shuf | head -100 | tr  '\n' ' ' 
\end{lstlisting}
\begin{lstlisting}
  shuf -n 100 /usr/share/dict/words | tr  '\n' ' '  ~(same, better)
\end{lstlisting}

\emph{ Substitute the word 'blah' in 'f.txt' with lots of random text }
\begin{lstlisting}
  sed "s/blah/$(shuf -n 100 /usr/share/dict/words | tr  '\n' ' ')/" f.txt
\end{lstlisting}

\emph{ The same, but really do the substitution in the file \& make a backup }
\begin{lstlisting}
  sed -i.bak "s/blah/$(shuf -n 100 /usr/share/dict/words | tr  '\n' ' ')/" f.txt
\end{lstlisting}

\emph{ Append contents of the file 'file.txt' to itself }
\begin{lstlisting}
  cat file.txt | tee >> file.txt
\end{lstlisting}

\subsection{Merging Text Files}

\emph{ Print lines between 2 markers }
\begin{lstlisting}
  awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
\end{lstlisting}

\emph{ Replace text between 2 markers sed or awk }
  -----
  SED:
  View Raw Code

      sed -i -e "/\^{}\#\#START?\$/,/\^{}\#\#STOP?\$/c \#\#START\textbackslash n\$$\{$REPLACEMENT$\}$\textbackslash n\#\#STOP" test 

      AWK:
      View Raw Code

  ,,,

          awk "/\#\#START/$\{$p=1;print\textbackslash "\#\#\#START\textbackslash n\$$\{$REPLACEMENT$\}$\textbackslash n\#\#\#STOP\textbackslash ";next$\}$/\#\#STOP/$\{$p=0;next$\}$!p" test.tmp $>$ test 

  To insert before the \#\#\#marker\#\#\# line :

// for each $<$line$>$ of second\_file.txt :
//   if $<$line$>$ matches regexp \#\#\#marker\#\#\#, outputs first\_file.txt.
//   **without any condition :** print $<$line$>$
awk '/\#\#\#marker\#\#\#/ $\{$ system ( ``cat first\_file.txt'' ) $\}$ \
     $\{$ print; $\}$ \textbackslash ' second\_file.txt

     To insert after the \#\#\#marker\#\#\#line :

     // for each $<$line$>$ of second\_file.txt :
     //   **without any condition :** print $<$line$>$
     //   if $<$line$>$ matches regexp \#\#\#marker\#\#\#, outputs first\_file.txt.
     awk '$\{$ print; $\}$ \
          /\#\#\#marker\#\#\#/ $\{$ system ( ``cat first\_file.txt'' ) $\}$ \textbackslash ' second\_file.txt

      To replace the \#\#\#marker\#\#\# line :

       // for each $<$line$>$ of second\_file.txt :
          //   if $<$line$>$ matches regexp \#\#\#marker\#\#\#, outputs first\_file.txt.
          //   **else**, print $<$line$>$
          awk '/\#\#\#marker\#\#\#/ $\{$ system ( ``cat first\_file.txt'' ) $\}$ \
               !/\#\#\#marker\#\#\#/ $\{$ print; $\}$' second\_file.txt

               If you want to do in-place replacement, use a temp file for being sure the pipe doesn't start before awk has read the entire file; add :

               $>$ second\_file.txt.new
               mv second\_file.txt$\{$.new,$\}$
               // (like "mv second\_file.txt.new second\_file.txt", but shorter to type !)

\subsection{Editing Text Files}

  The \$EDITOR variable determines the default text editor.

\emph{ Select and Edit a File in the Current Directory }
\begin{lstlisting}
  PS3="Enter a number: "; select f in *.txt;do $EDITOR $f; break; done
\end{lstlisting}

  But the command above breaks if any of the file names contain spaces
  You may be able to use the IFS variable to solve this.

\emph{ Choose a file to edit, even if the name contains a space }
\begin{lstlisting}
  IFS=$'\n'; PS3="Choose:"; select f in $(ls);do vim $f; break; done
\end{lstlisting}
 
\section{Searching Text}

\emph{ Search for comment lines in a file }
\begin{lstlisting}
  grep '^#' <file
\end{lstlisting}

\emph{ Search for some text in all files and subdirectories }
\begin{lstlisting}
  grep -ril text *
\end{lstlisting}

\emph{ Make searches within the 'less' pager case-insensitive  }
\begin{lstlisting}
  alias less='less -i'
\end{lstlisting}

\emph{ A function to search through files for the given words }
  \begin{lstlisting}
   function has {
    help=" - searches for files containing a given text"
    if [ -z "$1" ]; then
      echo -e "usage: $FUNCNAME searchterm \n $help" 
      return 3
    fi
    find . | xargs grep -l "$*" | less
    }
  \end{lstlisting}

\emph{ View all the files containing text 'screen saver'  }
\begin{lstlisting}
  has screen saver
\end{lstlisting}

\section{Remote Development}

\emph{ Using a remote shell }
\begin{lstlisting}
  putty (from MS Windows), ssh, telnet
\end{lstlisting}

\section{Streams}

  The idea of a 'stream' is very important in unix and 
  bash, since most work is carried out in this paradigm.
  Streams can be redirected and piped etc.

\emph{ Append stdout and stderr to a file, and print stderr to the screen }
\begin{lstlisting}
  somecommand 2>&1 >> logfile | tee -a logfile
\end{lstlisting}

\emph{ Add some text to the begging and end of standard input }
\begin{lstlisting}
  echo hello | (echo yes; cat -; echo no)
\end{lstlisting}

\section{Unix Threads}

  Unix provides several simple mechanisms for allowing 'threads' (also
  called processes, or running programs) to communicate between each other.
  This is probably the most powerful single feature of the unix operating
  system.

  see also: message queues, signals

\subsection{Redirection}

\emph{ Redirect stdout and stderr at the same time }
\begin{lstlisting}
  $>             ~(only the bash shell)
\end{lstlisting}
\begin{lstlisting}
  command 2>&1   ~(older style)
\end{lstlisting}

\emph{ Redirect both standard output error messages to the file ``output'' }
\begin{lstlisting}
  command > output.txt 2>&1
\end{lstlisting}

\emph{ Pipe stdout and stderr, etc., to separate commands }
\begin{lstlisting}
  some_command >>(/bin/cmd_for_stdout) 2>>(/bin/cmd_for_stderr)
\end{lstlisting}

\emph{ Redirect error messages to ``stdout'' and output to the file ``save.txt'' }
\begin{lstlisting}
  fond "dd" 2>&1 >save.txt
\end{lstlisting}

\emph{ Swap the stdout and stderr stream for the 'boggle' command }
\begin{lstlisting}
  boggle 3>&1 1>&2 2>&3
\end{lstlisting}
 
\emph{ Accept input from a file }
\begin{lstlisting}
  grep text <file
\end{lstlisting}

\emph{ Redirect output from multiple programs into another program }
\begin{lstlisting}
  diff -u <(ls -c1 dir1) <(ls -c1 dir2) 
\end{lstlisting}

\emph{ Save the output of ``sort'' in ``sorted'' and also pipe to ``uniq'' }
\begin{lstlisting}
  sort list.txt | tee sorted.txt |  uniq -c | less 
\end{lstlisting}

\emph{ Send a list of users to the printer and to a file ``users.txt'' }
\begin{lstlisting}
  awk -F: '{ print $1}' /etc/passwd | sort | tee users.txt | lp
\end{lstlisting}

\subsection{Tee}

\emph{ Show the date and also append it to 2 files }
\begin{lstlisting}
  date | tee -a file1 file2
\end{lstlisting}

\emph{ Record output of any command using 'tee' at backend }
\begin{lstlisting}
  ssh user@server | tee logfilename
\end{lstlisting}

\subsection{Pipes}

\emph{ Cat large file to clipboard with speed-o-meter }
\begin{lstlisting}
  pv large.xml | xclip
\end{lstlisting}

\emph{ Write text or append to a file }
\begin{lstlisting}
  cat <<.>> somefilename
\end{lstlisting}

\subsection{Complex And Named Pipes}

  \begin{itemize}
  \item 
    Named pipes are like files, they need to be explicitly deleted
    when they are no longer needed.
    \item 
    A named pipe can remove the need to save data to a temporary
    file
    \item 
\end{itemize}
  mknod and mkfifo are equivalent?

\emph{ A simple pipeline and its equivalent named pipe version }
  \begin{lstlisting}
    # the anonymous pipe version
    echo "test" | wc  
    # the named pipe version which is equivalent
    mknod apipe p; wc apipe; echo "test" > apipe
  \end{lstlisting}

\begin{lstlisting}
  sudo mkfifo mypipe; wc -l < mypipe >&1 ; ls > mypipe; rm mypipe;
\end{lstlisting}

\emph{ Create a named pipe which compresses things sent to it, send something }
\emph{ To it to get compressed and then delete it. }
  \begin{lstlisting}
    mkfifo mypipe
    gzip -9 -c < mypipe > out.gz
    cat file > mypipe
    rm mypipe
  \end{lstlisting}

\emph{ Create a pipe which compresses a file and loads the data into mysql }
  \begin{lstlisting}
    mkfifo /tmp/namedPipe
    chmod 0666 /tmp/namedPipe
    gzip -d file.gz > /tmp/namedPipe
    LOAD DATA INFILE '/tmp/namedPipe' INTO TABLE tableName;
  \end{lstlisting}

\emph{ Make some named pipes and redirect to them }
\begin{lstlisting}
  mkfifo pipe1 pipe2; ls | tee pipe1 | less  ~(delete pipe1 later) 
\end{lstlisting}

\emph{ Pipe the output of 2 commands to another command }
\begin{lstlisting}
  (cd /user/home && ls) | less 
\end{lstlisting}

\emph{ Who needs pipes? }
\begin{lstlisting}
  B <<< $(A)
\end{lstlisting}

\section{Multiple Commands}

\emph{ Only execute ``ls'' if the change directory ``cd'' command was successful }
\begin{lstlisting}
  cd /user/home && ls 
\end{lstlisting}

\section{Using File Handles}

\emph{ Open a for reading and give it the 'file handle' 3 }
\begin{lstlisting}
  exec 3< file.txt
\end{lstlisting}

\emph{ Open a file for reading and writing, write the text ``yes'', then close it }
\begin{lstlisting}
  exec 3<> file.txt ; echo yes >&3 ; exec 3>&- ;
\end{lstlisting}

\section{Loops}


  Bash has both 'while' and 'for' loops but sometimes it is possible
  to use 'xargs' or 'parallel' instead, which may be simpler and
  neater.

\emph{ An interpreting loop which breaks when the user enters 'q' }
\begin{lstlisting}
  while true; do read a; echo $a; [ "$a" = "q" ] && break; done
\end{lstlisting}

\emph{ Skip a broken piece of a loop but not exit the loop entirely }
\begin{lstlisting}
  ctrl + \
\end{lstlisting}

\emph{ Display files with 4 files on each line }
\begin{lstlisting}
  ls | xargs -L4
\end{lstlisting}

\emph{ Use xargs interactively prompting at each command }
\begin{lstlisting}
  ls | xargs -p -I{} cp "{}" "{}.bak" 
\end{lstlisting}

\emph{ Execute multiple commands for every 'wav' file (play/sleep)  }
\begin{lstlisting}
  locate '*.wav' | shuf | xargs -I{} echo "play {};sleep 2" | bash 
\end{lstlisting}

\subsection{Interpreting Loops}

  Interpreting loops can just receive an input from the user
  and do some action.

  The following script allows a user to create a transcription
  from an audio file (containing people speaking).

\emph{ A long loop doing audio stuff }
  \begin{lstlisting}
    #while read -sn 1 -p "?" com ; do 
    f=jenny.txt
    audio=jenny.wav

    at=0
    dur=0
    echo "An audio transcription script..."
    echo "audio file '$audio', transcription file '$f'"
    while read -sn 1 com ; do 
      echo $com
      if [ "$com" == "p" ]; then
        at=$[at + dur]
        start=$(date +'%s')
        echo "play from $at seconds"
        play -q $audio trim $at &
        pid=$!
        # echo "pid=$pid"
      fi
      if [ "$com" == "a" ]; then
        start=$(date +'%s')
        echo "play from ${at}s for $dur s"
        play -q $audio trim $at $dur &
      fi
      if [ "$com" == "s" ]; then
        #pkill play 
        kill -9 $pid 2>/dev/null
        end=$(date +'%s') 
        dur=$[end - start]
        echo "duration $dur"
      fi
      if [ "$com" == "b" ]; then
        read -p "Start time back (seconds):" new
        at=$[at - new]
        dur=0
      fi
      if [ "$com" == "f" ]; then
        read -p "Start time forward (seconds):" new
        at=$[at + new]
        dur=0
      fi
      if [ "$com" == "t" ]; then
        read -p "Enter new start time (seconds):" new
        at=$new
        dur=0
      fi
      if [ "$com" == "m" ]; then
        read -p "Enter new start time (minutes):" new
        at=$[new * 60]
        dur=0
      fi
      if [ "$com" == "w" ]; then
        echo "seconds: $at" >> $f 
        echo " " >> $f
        # start vim at last line in insert mode with easy exit (X/Z)
        vim +  -c 'nmap X :wq<cr>' -c 'nmap Z :wq<cr>' -c start $f
      fi
      if [ "$com" == "i" ]; then
        echo "transcription file: $f"
        echo "audio file: $audio"
        echo "current section duration (in seconds): $dur"
        echo "current play start point (in seconds): $at"
      fi
      if [ "$com" == "h" ]; then
        echo "p play"
        echo "a play same section again"
        echo "s stop playing"
        echo "b set start time back n seconds"
        echo "f set start time forward n seconds"
        echo "t enter a new start point in audio (in seconds)"
        echo "m enter a new start point in audio (in minutes)"
        echo "w transcribe"
        echo "i show info"
        echo "h show help"
        echo "x exit"
      fi
      if [ "$com" == "x" ]; then
        pkill play
        echo "goodbye!"
        exit
      fi
    done

  ,,,,



FOR LOOPS ....

  * show the bash help for the 'for' loop
  >> help for | less

  * a simple loop
  >> for j in 1 2 3 4; do echo "j=$j"; done

  * a for loop with variable and computed limit values
  >> a=4; for n in $(seq $a $((a+4))); do echo $n; done
  
  * an arithmetic style for loop
  >> for ((i=0; i<$MAX; i++)) do echo $i; done

  * in recent versions of bash we can use curly braces too.
  >> for j in 1 2 3 4;{ echo "j=$j"; }

  * print the numbers 1 to 20
  >> for j in $(seq 1 20); do echo "j=$j"; done
  >> for j in {1..20}; do echo "j=$j"; done   ##(bash 3.0 and after)

  * a for loop with leading zero in bash version 3
  >> for i in {0..1}{0..9}; do echo $i; done

  * for loop with leading zero in bash 3
  >> seq -s " " -w 3 20

  * print the numbers 1 to 20 with a step of 2
  >> for j in $(seq 1 2 20); do echo "j=$j"; done

  * loop through the files in a directory 
  >> for file in dir/*; do echo $file; done 

  * loop through the files in the current folder and subdirectories 
  >> for file in $(ls *); do echo $file; done 

  * find all file with names ending in '.html' or '.php' containing the word 'big'
  >> find / \(-name \*.html -o -name \*.php\) | xargs grep -i "big" 
  ##(this uses the tool 'xargs' instead of a 'for' loop)

  * a for loop with filling 0 format, with seq
  >> for i in `seq -f %03g 5 50 111`; do echo $i ; done

  * using 'jot' in a for loop 
  >> for f in `jot - 0 50 5` ; do ping -c 1 -m 50 10.0.2.$f ; done

  * nested brace expansion in a for loop
  \begin{lstlisting}
   for host in {frontend{1..5},backend{1..3}}.mycompany.com
   do
    ssh $host "echo -n $host; uptime"
   done
 \end{lstlisting}

\emph{ Loop over input line by line, not word by word  }
  \begin{lstlisting}
   IFS=$'\n'
   for f in $(ls -ls); do
     echo "loop=$f"
   done
  \end{lstlisting}

\emph{ Another way to read input line by line, not word by word  }
  \begin{lstlisting}
   ls -thor | while read f; do
     echo "loop=$f"
   done
  \end{lstlisting}

\subsection{While Loop}

\emph{ Show the bash help for 'while' }
\begin{lstlisting}
  help while
\end{lstlisting}

\emph{ Loop while the counter is less than 5 }
\begin{lstlisting}
  c=0; while [ $c -lt 5 ]; do echo c is $c; let c=c+1; done
\end{lstlisting}

\emph{ A loop which reads a line of text from the user infinitely }
\begin{lstlisting}
  while read s; do echo =$s; done
\end{lstlisting}

\emph{ A loop through files and delete each if user enters 'd'  }
\begin{lstlisting}
  for f in *; do echo $f; read x; [ "$x" == "d" ] && rm $f; done
\end{lstlisting}
  
\subsection{Infinite Loops}


\emph{ Make an infinite loop with while (stop it with $<$control c$>$) }
\begin{lstlisting}
  while true ; do echo yes; done
\end{lstlisting}
\begin{lstlisting}
  while test 1 ; do echo yes; done  ~(the same)
\end{lstlisting}
\begin{lstlisting}
  while [ 1 ] ; do echo yes; done   ~(the same)
\end{lstlisting}

\emph{ Loop until the user types 'q' using ``$>$'' as a prompt }
\begin{lstlisting}
  while [ "$r" != "q" ] ;do read -p'>' r; done; unset r
\end{lstlisting}

\subsection{Break And Continue}

  Break and continue are used within loops to skip certain
  iterations, for example to stop processing once a certain item
  it found within a list.

\emph{ Use break to break out of the loop }
\begin{lstlisting}
  for j in $(seq 1 20); do break; done   ~(does nothing)
\end{lstlisting}

\emph{ Continue goes immediately to the next iteration }
\begin{lstlisting}
  for j in $(seq 1 20); do continue; done   ~(does nothing)
\end{lstlisting}


\section{If Statement}


\emph{ Show the bash help for the 'if' command }
\begin{lstlisting}
  help if | less
\end{lstlisting}

\emph{ A basic if statement }
\begin{lstlisting}
  if [ ${f} == "xx" ]; then echo $f; fi
\end{lstlisting}

\emph{ A short-hand way of writing an 'if' statement }
\begin{lstlisting}
  [ this -eq this ] && echo 'true'   ~(prints 'true')
\end{lstlisting}

\emph{ A short hand way of writing an if else statement }
\begin{lstlisting}
  [ this -eq that ] && echo 'true' || echo 'false'
\end{lstlisting}

\emph{ Print a message and exit if no 'c' files are found in the folder }
\begin{lstlisting}
  ls *.c 2>/dev/null || { echo "No C files found"; exit; }
\end{lstlisting}

\subsection{If Else}

\emph{ Construct an if else alternative }
  \begin{lstlisting}
   if [ "1" == "" ]; then
     echo 'true'
   else
     echo 'false'
   fi
  \end{lstlisting}
   
\emph{ If with 'elif' (else if) statement }
\begin{lstlisting}
  if [ "${f} == "xx" ]; then echo $f; elif [ "${f} == "yy" ]; then echo $f; fi
\end{lstlisting}

\section{Case Statement}

\emph{ An example of a case statement }
  \begin{lstlisting}
   echo "choose"; read $o
   case "$o" in
     1) station="mms://server:port/path" ;;
     2) station="mms://otherserver:port/otherpath" ;;
     [3-9]) echo "wrong number"
     [[:lower:]]) echo "lower case"
     [qQ]) exit ;; 
     *) echo "invalid"
   esac
  \end{lstlisting}

\section{Tests}

  
  In the bash shell tests return either 0 (true) or 1 (false)

\emph{ Test if one number is less than another }
\begin{lstlisting}
  c=1; if [ $c -lt 5 ]; then echo $c; fi
\end{lstlisting}

\emph{ Test if the variable is a directory }
\begin{lstlisting}
  test -d "$HOME"; echo $?          ~(prints either 0 or 1)
\end{lstlisting}

\emph{ Combine two tests with the shell ``and'' operator }
  \begin{lstlisting}
  if [ -n "$var"] && [ -e "$var"]; then
     echo "\$var is not null and a file named $var exists!"
  fi
  \end{lstlisting}

\emph{ Combine two test with the ``and'' -a operator (a less common way) }
\begin{lstlisting}
  [ $c -lt 4 -a $c -gt 1 ]
\end{lstlisting}

\emph{ Combine two test with the ``or''  operator }
\begin{lstlisting}
  [ $c -lt 4 -o $c -gt 1 ]
\end{lstlisting}

\subsection{Negating Tests}

  The negation operator is the exclamation mark "!"

\emph{ A space between "!" and the next argument is necessary. }
\emph{ A space between '[' and '!' is also necessary  }

\emph{ Negate a test with a "!" symbol at the front of the test }
\begin{lstlisting}
  [ ! -e ~/plans.txt ] && echo "no plans"
\end{lstlisting}

  This prints ``no plans'' if the file ``plans.txt'' does not exist

\emph{ One can also use 'test' instead of the '[]' brackets  }
\begin{lstlisting}
  test ! -e ~/plans.txt && echo "no plans"
\end{lstlisting}

\emph{ Echo 'does not exist' if 'plans.txt' doesnt exist  }
  \begin{lstlisting}
   if test ! -e ~/plans.txt 
   then 
    echo "no plans"
   fi 
  \end{lstlisting}

\emph{ Test if a string variable is not empty }
\begin{lstlisting}
  i="  x"; test ! -z $i && echo "not empty"   ~(prints "not empty")
\end{lstlisting}

\section{File And Directory Names}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ moving around folders  }} \\
  \hline

  \texttt{ cd } & - go to the previous folder \\ 

  \texttt{ cd } & Go to the users home folder \\ 

  \texttt{ ls /usr/; cd !\$ } & Jump to the last folder mentioned \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ List only subdirectories in the current  }
\begin{lstlisting}
  ls -d */    
\end{lstlisting}
\begin{lstlisting}
  find -type d -maxdepth 1   ~(similar)
\end{lstlisting}

\emph{ Print file information in a readable format }
\begin{lstlisting}
  ls -thor    ~(this is more compact than 'ls -la')
\end{lstlisting}

\emph{ Find all dot files and directories }
\begin{lstlisting}
  echo .*
\end{lstlisting}

\emph{ A list of all files on one line separated by commas }
\begin{lstlisting}
  echo * | tr ' ' ','
\end{lstlisting}

\emph{ An alias to go back to the previous directory }
\begin{lstlisting}
  alias b='cd -'
\end{lstlisting}

\emph{ Strip out the path from a file name }
\begin{lstlisting}
  f=$(pwd); f=$(basename $f); echo $f  
\end{lstlisting}
  
\emph{ Display the fifth file in the current folder }
\begin{lstlisting}
  a=($(ls)); echo ${a[5]}
\end{lstlisting}

  This prints the current folder without the path.

\emph{ A bash shell alternative to 'basename' }
\begin{lstlisting}
  echo ${file##*/}
\end{lstlisting}

\emph{ Rename files replacing one text with another }
  \begin{lstlisting}
     for f in $(find . -name '*replaceme.jpg') ;
     do mv $f ${f/replaceme/withme}; done
  \end{lstlisting}

\emph{ Rename files ending in '.JPG' with '.jpg' even if file has a space in it }
\begin{lstlisting}
  locate '*.JPG' | xargs -I{} rename 's/\.JPG$/.jpg/' "{}"
\end{lstlisting}

  The '-n' option to ``rename'' is handy because it allows you to see 
  what would happen without actually doing it.

\emph{ Rename files replacing the extension ``.html'' with ``.php'' }
\begin{lstlisting}
  for f in *.html; do mv $f ${f/.html/.php}; done
\end{lstlisting}

\emph{ Display only directory names in a listing }
\begin{lstlisting}
  ls -l | grep '^d'
\end{lstlisting}

\emph{ Jump to the folder used in the last command }
\begin{lstlisting}
  ls /usr/share/doc/; cd !$
\end{lstlisting}

\emph{ Just the directory name of the last path entered }
\begin{lstlisting}
  !$:h 
\end{lstlisting}

\emph{ Just the file name of the last path entered }
\begin{lstlisting}
  !$:t
\end{lstlisting}

\subsection{File Name Extensions}

\emph{ Strip the suffix off a file name \$f }
\begin{lstlisting}
  echo ${f%.*}
\end{lstlisting}

 The above works even when the file name has dots in it.

\emph{ Rename files inserting '400w' just before file name suffix }
 \begin{lstlisting}
 for f in sf/img/*; do
    exten=${f##*.}
    echo exten=$exten
    newname=${f%.*}.400w.$exten
    echo newname=$newname
    convert -monitor -resize 400 $f $newname
    break;
  done
 \end{lstlisting}

\section{Finding Files}

  The 2 command line tools are 'find' and 'locate'. Locate is fast
  and simple, but cant find very recent files. Find is slow and complicated
  but can do everything.

\emph{ Find files with a '.mp3' extension }
\begin{lstlisting}
  locate -r '.mp3$'
\end{lstlisting}

\section{File Tests}

 

  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ Some file tests  }} \\
  \hline

  \texttt{ -d  } & Is the file a directory \\ 

  \texttt{ -f  } & Is the file a normal file (not a directory) \\ 

  \texttt{ -e  } & Does the file or folder exist \\ 

  \texttt{ -r  } & Is the file readable  \\ 

  \texttt{ -w  } & Is the file writeable \\ 

  \texttt{ -s  } & Is the file non-empty \\ 

  \texttt{ -S  } & Is the file a socket \\ 

  \texttt{ -z  } & Is the file or variable empty  \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Compare file ages }
\begin{lstlisting}
  -nt newer than, -ot older than
\end{lstlisting}

\emph{ Test if a file exists }
\begin{lstlisting}
  if [ -f file.ext ]; then echo ${file.ext}; done
\end{lstlisting}

\section{Scripts}

  A script is a set of bash commands placed into a text file
  and made executable. By convention bash script files often
  have a filename extension of '.sh' although this is not necessary.

  If your script is very small consider making it a function instead
  and place the function in the '.bashrc' configuration file


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ the steps to run a bash script }} \\
  \hline

  \texttt{ find out where you bash is with 'which bash' } \\ 

  \texttt{ put \#!/bin/bash at the top of the script (see previous step) } \\ 

  \texttt{ write your bash script } \\ 

  \texttt{ make your script executable with 'chmod +x script' } \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Make a script (text file) executable }
\begin{lstlisting}
  chmod +x list.sh
\end{lstlisting}

\emph{ Make a script (text file) executable for all users }
\begin{lstlisting}
  chmod a+x list.sh    
\end{lstlisting}

\emph{ A simple example script which lists a file }
  \begin{lstlisting}
    #!/bin/bash
    [ -z $1 ] && echo usage: $0 filename && exit
    cat $1
  \end{lstlisting}
  
\subsection{Executing Bash Scripts}

  Bash scripts are often given a file name extension of '.sh' 
  such as 'smallscript.sh' but this is not necessary.

\emph{ Place a reference to the bash executable at the top of the script }
\begin{lstlisting}
  #!/bin/bash     
\end{lstlisting}
  
  This is called the 'shebang' line - from hash-bang

\emph{ Execute a bash script called 'showpeople' in the current folder }
\begin{lstlisting}
  ./showpeople
\end{lstlisting}

\emph{ Execute a script which is in the 'tree' sub-folder }
\begin{lstlisting}
  tree/showpeople
\end{lstlisting}

  The methods above are the most usually way to execute to 
  a script.

\emph{ Another way to execute a script }
\begin{lstlisting}
  eval $(cat script)
\end{lstlisting}

\emph{ Execute a (non-executable) bash script }
\begin{lstlisting}
  source script ~(??)
\end{lstlisting}

\emph{ Find out where the 'bash' executable is on the computer }
\begin{lstlisting}
  which bash
\end{lstlisting}

\emph{ Execute the bash commands contained in the file 'script' }
\begin{lstlisting}
  cat script | bash
\end{lstlisting}

  Using the technique above, the file 'script' does not have 
  to be executable.

\emph{ Run the bash script 'script.sh' in debugging mode }
\begin{lstlisting}
  bash -x ./script.sh
\end{lstlisting}

\emph{ Run a bash script in debug mode, show output and save it }
\begin{lstlisting}
  bash -x script.sh 2> log
\end{lstlisting}
 
\emph{ Execute a shell script in the background and dont interrupt it }
\begin{lstlisting}
  nohup /bin/sh myscript.sh 1>&2 &>/dev/null 1>&2 &>/dev/null&
\end{lstlisting}

\emph{ Read commands from string and assign any arguments to positional params }
\begin{lstlisting}
  bash -c 'set w x y z; IFS=":-;"; echo "$*"'
\end{lstlisting}

\subsection{Script Parameters}

  
   This section deals with parameters which are passed from the
   command line to a Bash script.

\emph{ Get the absolute path to your bash-script }
\begin{lstlisting}
  scriptpath=$(cd $(dirname $0);pwd)
\end{lstlisting}

\emph{ Display a message and exit if no parameters were set }
\begin{lstlisting}
  [ -z "$1" ] && echo "no parameters were given" && exit 1
\end{lstlisting}

\emph{ Exit if exactly 3 parameters were not given }
  \begin{lstlisting}
   if [ $# -ne 3 ]; then
     echo "usage $0 <file> <to> <from>"
     exit 1
   fi
  \end{lstlisting}

\emph{ The string \$@ contains an array of all the parameters }
\begin{lstlisting}
  a="$@"
\end{lstlisting}

\emph{ All the parameters as a string not an array }
\begin{lstlisting}
  s="$*"
\end{lstlisting}
  
\emph{ Get the 2nd and rest of the parameters }
\begin{lstlisting}
  echo ${*:2}
\end{lstlisting}
\begin{lstlisting}
  echo ${@:2}
\end{lstlisting}
  
\emph{ Get the 2nd and 3rd parameters }
  \begin{lstlisting}
    echo ${@:2:3}
    if the script is invoked with
      ./script one 2 three 4
    then this will print
      "2 three"
  \end{lstlisting}

\emph{ Do something for each parameter given }
\begin{lstlisting}
  files="$@"; for f in files; do echo $f; done
\end{lstlisting}

\emph{ Show the number of script parameters }
\begin{lstlisting}
  echo $#
\end{lstlisting}

\emph{ Test if a particular parameter exists }
\begin{lstlisting}
  if test -z "$1" ;then exit; fi   ~(exits if no first parameter)
\end{lstlisting}
\begin{lstlisting}
  if [ -z "$1" ] ;then exit; fi    ~(the same)
\end{lstlisting}

\emph{ Assign a value to a variable depending if a parameter exists or not }
\begin{lstlisting}
  [ -z "$1" ] && x=”$1” || x="/bin/date"  (works ???)
\end{lstlisting}

\emph{ If 'foo' has no value, assign it the value 'one' }
\begin{lstlisting}
  foo=""; echo ${foo:=one}  ~(prints 'one')
\end{lstlisting}

\emph{ Maybe the quickest way to get the current program name minus the path }
\begin{lstlisting}
  programname="${0##*/}"
\end{lstlisting}

\subsection{Putting A Script In The Path}

\emph{ To execute a script without the './' set the path to a user 'bin' folder }
\begin{lstlisting}
  mkdir ~/bin; [in ~/.bashrc add] export PATH=$PATH:$HOME/bin
\end{lstlisting}
  
\emph{ Execute the 'showpeople' bash script which is located 'on the path' }
\begin{lstlisting}
  showpeople
\end{lstlisting}

  Another technique to make a bash script executable by everybody
  is to put a symbolic link to it in the '/usr/local/bin' folder.

\emph{ Put a symbolic link in the /usr/local/bin  }
\begin{lstlisting}
  ln -s /usr/local/bin/go ~/scripts/super.sh (wrong ??)
\end{lstlisting}

\emph{ Search for a file in the system path   }
\begin{lstlisting}
  type <filename>
\end{lstlisting}
 
\subsection{Script Configuration}

\emph{ Check the bash version number in a script }
  \begin{lstlisting}
   if [[ $BASH_VERSION > "2.05a" ]]; then
     ...
   fi
  \end{lstlisting}

\emph{ Check if the script has been run as root }
  \begin{lstlisting}
    if [ $(id -u) != 0 ]; then
      echo "This script must be run as root" 1>&2
      exit 1
    fi
  \end{lstlisting}

\section{User Interaction}



  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ tools }} \\
  \hline

  \texttt{ read } & Allow the user to input some text  \\ 

  \texttt{ select } & Presents the user with a list to select from \\ 

  \texttt{ whiptail } & Displays 'dialog boxes' in a shell window \\ 

  \texttt{ dialog } & Like whiptail \\ 

  \texttt{ osd\_cat } & Display text on the desktop (not is the console) \\ 

  \texttt{ zenity } & Display nice windows from shell scripts (uses gtk) \\ 

  \texttt{ kdialog } & Like zenity but for the kde linux desktop  \\ 

  \texttt{ wish } & Run a tk window script  \\ 

  \texttt{ complete } & Automatically completes commands \\ 

  \texttt{ perl tk } & Display windows from within a perl script  \\ 

  \texttt{ gtk } & A library for writing window applications \\ 

    \hline
    \end{tabular}
    \end{center}
 Traditionally Unix and Linux was the domain of command line hackers who
 enjoyed hours of typing cryptic commands into a black screen with green text
 in a strange language devoid of vowels and meaning. But the fact remains that
 the average human being has a gut-instinct aversion to being forced to using
 the command line to do things. It is possible to use various Linux tools to
 present the user with a slightly more enjoyable interface.


\subsection{User Input}

  The easiest way to interact with the user is just to ask the 
  user to enter some information at a shell prompt. This can be
  down with the 'read' command.

\emph{ Display a prompt and get a response from the user }
\begin{lstlisting}
  echo enter name; read s; echo you typed $s;
\end{lstlisting}

\emph{ Get more than one value from the user }
\begin{lstlisting}
  read d m; echo day $d month $m
\end{lstlisting}

\emph{ Get a single key press from the user }
\begin{lstlisting}
  echo press key; key=$(dd bs=1 count=1 2> /dev/null); echo $key;
\end{lstlisting}

  see http://tldp.org/LDP/abs/html/commandsub.html for more 
  information (the terminal mode needs to be changed first)

\emph{ Press any key to continue }
\begin{lstlisting}
  read -sn 1 -p "press any key to continue..."; echo
\end{lstlisting}

\emph{ Function that outputs dots every second until command completes }
\begin{lstlisting}
  sleeper(){ while `ps -p $1 &>/dev/null`; do echo -n "${2:-.}"; sleep
\end{lstlisting}

\emph{ Display todays date on the desktop }
\begin{lstlisting}
  date | osd_cat
\end{lstlisting}

\emph{ Display a webpage as text and update the view it every 10 seconds }
\begin{lstlisting}
  watch --interval=10 lynx -dump http://dslrouter/stats.html
\end{lstlisting}

\emph{ A loop through files and delete each if user enters 'd'  }
\begin{lstlisting}
  for f in *; do echo $f; read x; [ "$x" == "d" ] && rm $f; done
\end{lstlisting}
  
\subsection{Dialog And Whiptail}

  Whiptail and dialog are basically one step up from 
  'select', and one step down from 'yad' and 'zenity'. Dialog and
  whiptail are basically equivalent, but are both quircky and
  less useful than they should be.

  Whiptail installed by default on most debian systems

\emph{ A whiptail menu with a return value }
\begin{lstlisting}
  r=$(whiptail --title "files" --menu "choose" 20 60 15 a app b ball c cat 3>&1 1>&2 2>&3); echo $r
\end{lstlisting}

\emph{ With brace expansion }
\begin{lstlisting}
  r=$(whiptail --title files --menu "choose" 20 60 15 {A..z} 3>&1 1>&2 2>&3); echo $r
\end{lstlisting}

\emph{ A whiptail file listing }
\begin{lstlisting}
  r=$(whiptail --title files --menu "choose" 20 60 13 $(ls | sed "s/$/ ./" | tr '\n' ' ';) 3>&1 1>&2 2>&3); echo $r
\end{lstlisting}

\emph{ Show a 'curses' based menu selector }
\begin{lstlisting}
  whiptail --checklist "Simple checkbox menu" 11 35 5 tag item status repeat tags 1
\end{lstlisting}

\emph{ A trick to get a return value from whiptail }
\begin{lstlisting}
  foobar=$(whiptail --inputbox "Enter some text" 10 30 3>&1 1>&2 2>&3)
\end{lstlisting}

\emph{ Return values from dialog are more easily got }
\begin{lstlisting}
  result=$(dialog --output-fd 1 --inputbox "Enter some text" 10 30)
\end{lstlisting}

\subsection{Present A Choice To The User}

  The 'select' tool is a simple way to present the user with a 
  choice and perform and action based on that choice. 

\emph{ Choose a file in the current folder to edit }
\begin{lstlisting}
  PS3="Enter a number: "; select f in *; do vim $f; break; done
\end{lstlisting}


\begin{center}
  \includegraphics[width=0.4\textwidth]{image/eg-select-edit.png}
\end{center}

\emph{ Choose an image for a list and open it }
\begin{lstlisting}
  IFS=$'\n'; select f in $(locate -i '/home/*.jpg'); { xdg-open $f; break; }
\end{lstlisting}
  
  Notice that select can use curly braces (like 'for') is modern versions
  of the bash shell.

\emph{ Set the 'IFS' variable if file names may contain spaces }
\begin{lstlisting}
  IFS=$'\n'; PS3="Choose dir:"; select f in $(find . -type d);{ cd $f;break;}
\end{lstlisting}

\emph{ A function to list folders named with some text and jump to selected }
\begin{lstlisting}
  ju() { PS3="dir:"; select f in $(find ~ -type d -iname "*$1*"); do cd $f; break; done; }; ju doc;
\end{lstlisting}

\emph{ Choose from 2 phrases to print }
\begin{lstlisting}
  select f in "1 ball" "2 balls"; do echo $f; break; done
\end{lstlisting}

\emph{ Choose a big file to delete }
\begin{lstlisting}
  select f in $(find . -size +2M); { rm $f; echo $f; break; }
\end{lstlisting}

\emph{ Present the user with a choice of options }
  \begin{lstlisting}
   if [ "1" == "" ]; then
     echo "
      [1]   Radio 1
      [2]   Radio 2
      Enter your choice: "
     read choice
   else
     choice="1"
   fi
   case "$choice" in
     1) station="mms://server:port/path" ;;
     2) station="mms://otherserver:port/otherpath" ;;
     *) echo "Wrong choice!" exit
   esac
  \end{lstlisting}

\emph{ Use select to jump to a line in a text file containing the text 'determ'  }
  \begin{lstlisting}
    IFS=$'\n'; PS3="Choose:"; n=bash-book.txt; 
    select f in $(grep -n determ $n)
    do
      l=$(echo "$f" | cut -d' ' -f2)
      vim +$l $n; break;
    done
  ,,,,

  Notice the judicious use of the 'IFS' variable above. IFS determines how
  input will be split into elements. By default it will split all input on
  all whitespace (that is, into words) but here we want it to split the
  input into lines so we have to set IFS to only the new-line character. 

  The problem is that if the output contains more lines than the screen,
  the user will never see the beginning of the output.

  * use select to jump to a line in a text file containing the text 'determ' 
  \begin{lstlisting}
    IFS=$'\n'; PS3=""; n=test.txt; select f in $(grep -n determ $n); do l=$(echo "$f" | cut -d' ' -f2); vim +$l $n; break; done
  ,,,,

  * search for a word in 'words' then jump to the one selected in a window
  >> f=/usr/share/dict/words; vim +/$(grep -i jump $f | zenity --list --column= --height=800)/ $f

  * try to kill a process chosen by the user
  >> IFS=$'\n'; PS3="which?:"; select f in $(ps -ef|tr -s ' ');{ echo $f;break;}

YAD ....

  Yad is a replacement for zenity, and is much better.

ZENITY .... 

  zenity is a way of easily displaying windows with user
  interface elements which allow the user to carry out
  actions or answer questions etc. Or use tcl/tk

  * view the man page for zenity
  >> man zenity 

  * show a calender in a window 200 by 800 pixels
  >> zenity --calendar --title 'select a file' --height=800 --width=200

  * show a list box 800 pixel high and 800 pixels wide
  >> ls -thor | zenity --list --column=  --height=800 --width=800

FILE SELECTION ........

  * allow the user to select a file and echo the name of the chosen file
  >> zenity --file-selection --title 'select a file'
  
  * select a file in the /home/bob/os/ folder 
  >> zenity --file-selection --filename="/home/bob/os/" 

  * a function which searches for files and then opens the selected one
  \begin{lstlisting}
    function op {
      [ -z "$1" ] && echo "usage: $FUNCNAME <file>" && return 1;
      xdg-open "$(find ~ -iname '*$1*' | zenity --list --column= --width=700 --height=700)"
    }
  \end{lstlisting}


\emph{ Display a list of all pngs on the computer and display selected one }
\begin{lstlisting}
  locate '*.png' | zenity --list --column=Images | xargs -I{} xdg-open "{}"
\end{lstlisting}

  The 'xargs -I$\{$$\}$ xdg-open ``$\{$$\}$''' is important for the case where
  a file name contains a space.

\emph{ Locate all jpgs in user home folders }
\begin{lstlisting}
  xdg-open "$(locate -i '/home/*.jpg' | zenity --list --column=)"
\end{lstlisting}
  
  The recipe above also handles filenames with spaces in them, owing to 
  the judicious use of double quotes

\begin{lstlisting}
  xdg-open "$(locate -i '/home/*.jpg' | zenity --list --column=)"
\end{lstlisting}

\subsubsection{Text Entry}

\emph{ Display a dialog which allows the user to enter some text }
\begin{lstlisting}
  zenity  --title="New File" --entry
\end{lstlisting}

\emph{ Display a window titled 'Name' with a text box and text prompt }
\begin{lstlisting}
  zenity  --title "Name"  --entry  --text "Enter your name"
\end{lstlisting}

\subsubsection{List Boxes}

\emph{ Make a window with a list-box with the files from current folder }
\begin{lstlisting}
  ls | zenity --list --column="test" --title='choose a file'
\end{lstlisting}
 

\begin{center}
  \includegraphics[width=0.4\textwidth]{image/eg-zenity-list.png}
\end{center}
  
\emph{ Display a list of folders in the current folder with no window title  }
\begin{lstlisting}
  ls -d */ | zenity --list --column="test" 
\end{lstlisting}

\emph{ Display a list of files in a window with no title or column-title }
\begin{lstlisting}
  ls | zenity --list --column=
\end{lstlisting}

\emph{ Show a list of files and then display the file-name which was chosen  }
\begin{lstlisting}
  echo "you chose $(ls | zenity --list --column=)"
\end{lstlisting}

\emph{ Jump to any folder in the current folder  }
\begin{lstlisting}
  cd $(ls -d */ | zenity --list --column= --title="change folder")
\end{lstlisting}

\emph{ Jump to any folder in the users home directory (could be slow) }
\begin{lstlisting}
  cd $(find ~ -type d | zenity --list --column= )
\end{lstlisting}

\emph{ An alias to display lists with the zenity tool }
\begin{lstlisting}
  alias zenls='zenity --list --column='
\end{lstlisting}

  We can then use the alias above in a command pipe-line such as
\begin{lstlisting}
  ls | zenls
\end{lstlisting}

\emph{ Make an editable text box with a file listing saving changes to 'j.txt' }
\begin{lstlisting}
  ls | zenity --text-info --editable > j.txt
\end{lstlisting}

\subsection{Multicolumn List Boxes}

\emph{ Create a list with 2 columns, one all 'false' and the other files }
\begin{lstlisting}
  zenity --list --column=buy --column=item $(echo * | sed 's/ / FALSE /g;s/^/FALSE /')
\end{lstlisting}
ls | tr '\textbackslash n' ' ' 

\emph{ Create a list with 2 columns, the first check-boxes and the other files }
\begin{lstlisting}
  zenity --checklist --list --column=buy --column=item $(echo * | sed 's/ / FALSE /g;s/^/FALSE /')
\end{lstlisting}

\emph{ A zenity mulicolumn example checkbox example }
\begin{lstlisting}
  zenity --list --checklist --column=Buy --column=Item TRUE "Red Apples" TRUE Oranges FALSE 'Green Pears' FALSE Toothpaste
\end{lstlisting}

 

  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ some zenity options }} \\
  \hline

  \texttt{ --text ``hello'' } & Display hello at the top of the window \\ 

  \texttt{ --column ``file'' } & Display 'file' at the top of the column \\ 

    \hline
    \end{tabular}
    \end{center}
ZENITY NOTIFICATIONS ...
  
\emph{ Show an icon in the notification area }
\begin{lstlisting}
  zenity --notification --window-icon=up.png --text "System update necessary!"
\end{lstlisting}

\section{Kdialog}

\subsection{Tk And Tcl}

  It should be possible to use the 'wish' interpreter and the tk language
  to interact with the user in a 'graphical' fashion from a bash script,
  but this is a large topic.

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://pages.cpsc.ucalgary.ca/~saul/personal/archives/Tcl-Tk_stuff/tcl_examples/}] some tk examples
\end{description}

\emph{ A simple tk label example }
  \begin{lstlisting}
    label .l1 -text "ground" -foreground blue 
    label .l2 -text "big" -font {-family times -size 24}
    grid .l1 -row 0
    grid .l2 -row 1
  \end{lstlisting}

\emph{ Buttons }
  ---------
    !/usr/bin/wish
    button .my\_button -text ``Hello World'' -command exit
    pack .my\_button
  ,,,

\emph{ A button which exits when clicked }
\begin{lstlisting}
  echo 'button .b -text "Hello World" -command exit; pack .b' | wish
\end{lstlisting}


\begin{center}
  \includegraphics[width=0.2\textwidth]{image/eg-tk-button-exit.png}
\end{center}

\emph{ A tk list-box with text items and file names }
\begin{lstlisting}
  (echo -n 'listbox .lb -selectmode multiple -height 14; .lb insert 0 sample stuff colors red yellow green '; echo -n * ; echo '; pack .lb') | wish 
\end{lstlisting}
     

\begin{center}
  \includegraphics[width=0.2\textwidth]{image/eg-tk-listbox-files.png}
\end{center}

\emph{ Another way to execute some tk or tcl commands }
\begin{lstlisting}
  cat script | wish
\end{lstlisting}

\subsection{Perl Tk}

  Using perl with 'tk' is another way to interact with
  the user graphically.

\emph{ Install perl/tk with apt on a debian linux type system }
\begin{lstlisting}
  apt-get install perl-tk
\end{lstlisting}
 
\emph{ Another way to try to install the perl 'Tk' module }
\begin{lstlisting}
  perl -MCPAN -e 'install "Tk"' ~(didnt work!!)
\end{lstlisting}

\emph{ View the very good help for the perl tk module }
\begin{lstlisting}
  man perl-tk
\end{lstlisting}

\emph{ Run the demonstration program showing all perl tk possibilities }
\begin{lstlisting}
  widget
\end{lstlisting}


\begin{center}
  \includegraphics[width=0.4\textwidth]{image/eg-perltk-widget.png}
\end{center}

\emph{ A perl-tk one liner to create a button }
\begin{lstlisting}
  echo "use Tk; new MainWindow->Button(-text=>'click!')->pack; MainLoop;" | perl
\end{lstlisting}

\emph{ Tk example }
  \begin{lstlisting}
    #!/usr/bin/perl -w
    use Tk; use strict;
    my $main = new MainWindow;
    my $button = $main->Button();
    $button -> configure(-text => 'Press me!');
    $button -> pack;
    MainLoop; 
  \end{lstlisting}

\emph{ Display a directory tree. }
  \begin{lstlisting}
  use Tk;
  use Tk::DirTree;
  my $top = MainWindow->new;
  my $dl  = $top->Scrolled('DirTree')->pack(-expand => 1, -fill => 'both');
  MainLoop;
  \end{lstlisting}

\section{Program Output}


\emph{ Suppress program output messages }
\begin{lstlisting}
  prog &> /dev/null
\end{lstlisting}

\emph{ Suppress error messages }
\begin{lstlisting}
  prog 2> /dev/null
\end{lstlisting}

\emph{ Print the return value of a program }
\begin{lstlisting}
  prog; echo $?
\end{lstlisting}

\emph{ Return a value to the shell }
\begin{lstlisting}
  exit 31      ~(exits the script and returns 31)        
\end{lstlisting}

\section{Randomness}

\emph{ Play a random 'wav' sound file, but it fails if names have spaces }
\begin{lstlisting}
  a=($(ls *.wav)); play "${a[$RANDOM%${#a}]}" 
\end{lstlisting}

\emph{ Play a random wav file in the current folder   }
\begin{lstlisting}
  f=$(ls *.wav | sed -n "$[$RANDOM%$(ls | wc -l)]p" ); play "$f"
\end{lstlisting}

\emph{ Play a random wav, but this gives an error if no wavs available }
\begin{lstlisting}
  play "$(ls *.wav | shuf | head -1 )"
\end{lstlisting}

\emph{ Only print a message sometimes (randomly)  }
\begin{lstlisting}
  (($RANDOM%6)) || echo 'hello world!'
\end{lstlisting}

\emph{ Display a random file in the current folder }
\begin{lstlisting}
  a=($(ls)); echo ${a[$RANDOM%${#a}]}
\end{lstlisting}

\emph{ Randomly shuffle lines of a file (but needs gnu sort, not bsd) }
\begin{lstlisting}
  sort --random-sort
\end{lstlisting}

\emph{ Another random file lines sort }
\begin{lstlisting}
  cat test.txt | while read f ; do printf "$RANDOM\t%s\n" "$f"; done | sort -n | cut -f2-
\end{lstlisting}

\emph{ Shuffle lines in a file on a system without 'shuf' }
\begin{lstlisting}
  cat /usr/share/dict/words | perl -MList::Util -e 'print List::Util::shuffle <>' | less
\end{lstlisting}
\begin{lstlisting}
  perl -MList::Util=shuffle -e'print shuffle<>'
\end{lstlisting}

\section{Special Variables}


\emph{ The script name is contained in \$0 }
\begin{lstlisting}
  echo usage: $0 filename     
\end{lstlisting}

\emph{ \$? contains 0 or 1 the result of the last program (or test) }
  
\emph{ The process id of the script }
\begin{lstlisting}
  $$
\end{lstlisting}

\section{Special Characters}

\emph{ Add 2 newlines to a string variable }
\begin{lstlisting}
  s="tree"$'\n'$'\n'; echo "$s"  ~(try "echo $s" to see an echo "gotcha")
\end{lstlisting}

\section{Bash Expansion}

\subsection{Command Completion}

\emph{ Execute the last command }
\begin{lstlisting}
  !!
\end{lstlisting}

\emph{ Execute the last command entered with root privileges }
\begin{lstlisting}
  sudo !!
\end{lstlisting}

\emph{ Enter the last command typed on the command line }
\begin{lstlisting}
  alt + .
\end{lstlisting}
 
\emph{ Inserts the last used arguments }
\begin{lstlisting}
  <esc> .
\end{lstlisting}

\emph{ Inserts the results of an auto-completion in the command line }
\begin{lstlisting}
  ESC *
\end{lstlisting}

\subsection{Configuring Command Completion}

\emph{ Some useful settings in $\sim$/.inputrc: }
  \begin{lstlisting}

   set completion-ignore-case on
   set show-all-if-ambiguous on
   set show-all-if-unmodified on
  \end{lstlisting}

\emph{ Enable ** to expand files recursively ($>$=bash-4.0) }
\begin{lstlisting}
  shopt -s globstar
\end{lstlisting}

\emph{ Enable automatic typo correction for directory names }
\begin{lstlisting}
  shopt -s cdspell
\end{lstlisting}

\emph{ Bash autocomplete case insensitive search }
\begin{lstlisting}
  shopt -s nocaseglob
\end{lstlisting}

\emph{ Bash glob dot-files (such as '.bashrc') }
\begin{lstlisting}
  shopt -s dotglob
\end{lstlisting}

\section{Lists In Bash}

  Bash has several methods of generating lists, including
  ``globbing'', and ``brace expansion''. 

\subsection{Globbing}

\emph{ Rename a file using special brace expansion  }
\begin{lstlisting}
  cp /long/path/file.{txt,doc}
\end{lstlisting}

\emph{ Assign a list of folder names to a variable }
\begin{lstlisting}
  d=$(echo */); echo $d
\end{lstlisting}

  Be careful here: ``d=*/; echo \$d'' appears to have the desired effect
  but in reality, the variable 'd' does not contain a list, just the
  characters '*/'
 
\emph{ Get a list of folder names and replace all '/' with ':' }
\begin{lstlisting}
  d=$(echo ~/sf/htdocs/books/*/); echo ${d//\//:}
\end{lstlisting}

\emph{ Get a list of folder names but only print the last element of the path  }
\begin{lstlisting}
  d=$(echo ~/sf/htdocs/*/); d="basename "${d// /;basename }; eval $d
\end{lstlisting}

  The recipe above is fairly nifty. It used globbing, string substitution
  and 'eval' to execute the bash commands, contained in the variable "d".
  In these capabilities it gets close to the power of a functional or 
  ``list-based'' language such as lisp.

\emph{ Get a list of folder names and double up each folder name }
\begin{lstlisting}
  d=$(echo ~/sf/htdocs/*/); d="basename "${d// /;basename }; d=$(eval $d); echo $d | sed 's/\w\+/& &/g'
\end{lstlisting}
  This prints some like 'docs docs html html img img ...' etc


\subsection{Arithmetic Brace Lists}

\emph{ Print the numbers from 1 to seven   }
\begin{lstlisting}
  echo {1..7}      ~(modern bash versions)
\end{lstlisting}

\emph{ Enumerate with the numbers padded with zeroes }
\begin{lstlisting}
  echo {001..5}
\end{lstlisting}

\emph{ A for loop with leading zero (bash version 3) }
\begin{lstlisting}
  for i in {0..1}{0..9}; do echo $i; done
\end{lstlisting}

\emph{ Use a brace arithmetic series with a 'step' value (bash version 4)  }
\begin{lstlisting}
  echo {1..20..2}
\end{lstlisting}

\section{Brace Expansion}

  Brace expansion is another way of generating lists of strings
  in the bash shell. In some ways this is reminiscent of list based
  programming languages, such as 'lisp' or 'scheme'. ``Globbing'' is
  another technique for generating lists of file names.

\emph{ Use a numeric sequence 'glob' (expansion) to create speech }
\begin{lstlisting}
  echo {1..3}" o'clock" ROCK | espeak
\end{lstlisting}

\emph{ Print an alphabetic expansion }
\begin{lstlisting}
  echo {a..z}"x "          ~(prints 'ax bx cx ... zx')
\end{lstlisting}

\emph{ Multiply by nothing, zero string, create a file list }
\begin{lstlisting}
  echo *.html{"",.gz}
\end{lstlisting}

\emph{ Use an explicit list for with brace expansion  }
\begin{lstlisting}
  echo n:{pin,nail,ball}
\end{lstlisting}
  This will print 'n:pin n:nail n:ball'
  
\emph{ An html style brace expansion }
\begin{lstlisting}
  echo "<li>"{a..z}"</li>"   
\end{lstlisting}

\emph{ Dynamic globbing can be done like this }
\begin{lstlisting}
  e=4; eval "echo {1..$e}"; echo {1..4}
\end{lstlisting}

\emph{ Print a comma delimited file list }
\begin{lstlisting}
  a=$(echo *); echo ${a//" "/, }
\end{lstlisting}

\emph{ Print a colon delimited list of folders in the current folder }
\begin{lstlisting}
  a=$(echo */); echo ${a//" "/:}
\end{lstlisting}

\emph{ Do a 'dynamic' brace expansion on a list of file names }
\begin{lstlisting}
  echo "echo "{$(echo * | tr ' ' ',')}"xx" | bash
\end{lstlisting}

\emph{ Another way }
\begin{lstlisting}
  a=$(echo *); echo 'echo file:{'${a//" "/,}} | bash
\end{lstlisting}

\emph{ Make the listing one per line with the -e switch  }
\begin{lstlisting}
  a=$(echo *); echo 'echo -e "\nfile:{'${a//" "/,}} | bash
\end{lstlisting}

\emph{ Make an html directory listing out of the current folder }
\begin{lstlisting}
  echo "echo \<li\>"{$(echo * | tr ' ' ',')}"\</li\>" | bash
\end{lstlisting}

  The technique used above could equally be done using a 'for' loop such
  as 'for f in *; do ... ; done' but I find this brace expansion concept
  interesting.

\emph{ Make 2 backups of a file using brace expansion }
\begin{lstlisting}
  cp list{,bak,bak1}
\end{lstlisting}

\emph{ Using nested string brace expansion (bash version $>$= 3.0) }
\begin{lstlisting}
  echo {frontend{1..5},backend{1..3}}.server.net
\end{lstlisting}

\emph{ List all the directories in the current folder  }
\begin{lstlisting}
  echo */
\end{lstlisting}
\begin{lstlisting}
  ls -d */
\end{lstlisting}
\begin{lstlisting}
  ls -F | grep '/$'
\end{lstlisting}

\emph{ List all hidden files (starting with '.') in the current folder }
\begin{lstlisting}
  echo .*
\end{lstlisting}


\section{Executing Bash Commands}

\emph{ Find out where the 'wget' program is }
\begin{lstlisting}
  type -a wget
\end{lstlisting}
\begin{lstlisting}
  which wget    ~(similar)
\end{lstlisting}

\emph{ Execute bash commands from standard input }
\begin{lstlisting}
  echo "cd /; ls" | bash
\end{lstlisting}

\emph{ Execute commands in a string }
\begin{lstlisting}
  bash -c 'ls'
\end{lstlisting}

\emph{ Remove lots of files, but first check which ones will be removed }
\begin{lstlisting}
  find dir -name \*~ | xargs echo rm
\end{lstlisting}
\begin{lstlisting}
  find dir -name \*~ | xargs echo rm | bash
\end{lstlisting}

\emph{ Use eval to execute the command 'ls' }
\begin{lstlisting}
  eval 'l''s'
\end{lstlisting}

\section{Command Substitution}


\emph{ Delete a list of files named in a text file }
\begin{lstlisting}
  rm `cat file`
\end{lstlisting}
\begin{lstlisting}
  rm $(cat file)      ~(this is the same)
\end{lstlisting}

\emph{ Execute a command which is contained in a variable }
\begin{lstlisting}
  cmd=ls; $cmd
\end{lstlisting}

\section{Process Substitution}

\emph{ Compare the packages installed on 2 servers }
\begin{lstlisting}
  diff <(ssh server1 'rpm -qa | sort') <(ssh server2 'rpm -qa | sort')
\end{lstlisting}

\section{Variable Assignment}

  
\emph{ Use export to make a variable available to subprocesses }
\begin{lstlisting}
  export name=value
\end{lstlisting}

\emph{ Set a variable to the contents of a file }
\begin{lstlisting}
  v=$(<file)
\end{lstlisting}
\begin{lstlisting}
  v=$(cat file);     ~(the same)
\end{lstlisting}

\section{Variable Type}

  Variables in bash are normally 'untyped' but can be 
  declared as a certain 'type' using the 'declare' keyword

\emph{ Check if a variable is not a number  }
\begin{lstlisting}
  v='blah';if [ -z $(echo $v | grep [0-9]) ]; then echo "NON NUMERIC"; fi
\end{lstlisting}

\emph{ Check if a variable is not a number  }
\begin{lstlisting}
  v='1';[ -z $(echo $v | grep [0-9]) ] && echo "not a number" || echo 'number'
\end{lstlisting}
 
\emph{ Declare variable as integer }
\begin{lstlisting}
  declare -i aa ; aa=3*8 ; echo $aa
\end{lstlisting}
\begin{lstlisting}
  declare -i aa ; aa=3*8 ;aa='tree'; echo $aa
\end{lstlisting}

  If a string is assigned to the variable then the variable will
  be set to '0'.

\section{Arithmetic}
  
\subsection{Even And Odd}

\emph{ Check if a number is even }
\begin{lstlisting}
  [ $((a%2)) -eq 0 ] && echo "even"
\end{lstlisting}

\emph{ Check if no of files in dir is even or odd }
\begin{lstlisting}
  n=$(ls | wc -l); [ $((n%2)) -ne 0 ] && echo "odd"
\end{lstlisting}

\emph{ Define a quick calculator function '?' }
\begin{lstlisting}
  ? () { echo "$*" | bc -l; }
\end{lstlisting}
  
  The function above can be called with '? 4*5' for example,
  which will print '20'.

\emph{ Add two numbers using bash operators }
\begin{lstlisting}
  echo $((4+5))
\end{lstlisting}
\begin{lstlisting}
  echo $[4+5]
\end{lstlisting}
  
\emph{ Perform addition with the 'bc' tool }
\begin{lstlisting}
  echo 1+1|bc
\end{lstlisting}

\emph{ C style variable incrementation,  }
\begin{lstlisting}
  a=8; (( a++ )); echo $a;       ~(prints 9)
\end{lstlisting}

\emph{ Integer arithmetic and assignment }
\begin{lstlisting}
  a=3; b=$(( a + 5 )); echo $b;  ~(prints 8)
\end{lstlisting}

\emph{ Add up all the numbers from 1 to 1000 }
\begin{lstlisting}
  echo {1..1000} | sed 's/ \+/+/g' | bc
\end{lstlisting}
\begin{lstlisting}
  seq 1 1000 | (sed 's/^/x+=/'; echo x) | bc   ~(another way)
\end{lstlisting}

\emph{ Sum all the numbers in the file 'list.txt' with each number on a line  }
\begin{lstlisting}
  (sed 's/^/x+=/' list.txt ; echo x) | bc
\end{lstlisting}

\emph{ Display the product of 512 and 7 }
\begin{lstlisting}
  expr 512 \* 7
\end{lstlisting}

\emph{ Creating a list of numbers for calculation }
\begin{lstlisting}
  echo $( du -sm /var/log/* | cut -f1 ) | sed 's/ /+/g'
\end{lstlisting}
 
\emph{ A short counter }
\begin{lstlisting}
  yes '' | cat -n
\end{lstlisting}
 
\subsection{Floating Point Arithmetic}

  Unfortunately many linuxes dont come with 'bc' installed by
  default, which means you may not be able to rely on these
  techniques.

\emph{ Divide 22 by 23 and print result to 4 decimal places  }
\begin{lstlisting}
  echo "scale=4; 22/23" | bc
\end{lstlisting}
 
\emph{ Subtract one decimal number from another }
\begin{lstlisting}
  echo "4.54-6.332" | bc
\end{lstlisting}

\emph{ A floating point operation with no precision specified  }
\begin{lstlisting}
  echo 7/2 | bc -l               ~(prints 3.50000000)
\end{lstlisting}

\emph{ Another way but not working!!?? }
\begin{lstlisting}
  bc -l <<< s(3/5)
\end{lstlisting}
 
\section{Integer Variables}

\emph{ Declare variable as integer }
\begin{lstlisting}
  declare -i aa ; aa=3*8 ; echo $aa
\end{lstlisting}

\emph{ Print 'yes' if the variable 'x' is a number }
\begin{lstlisting}
  i=3; if [ "$i" -eq "$i" 2>/dev/null ]; then echo yes; fi
\end{lstlisting}

\emph{ Increment a variable }
\begin{lstlisting}
  c=4; let c=c+1;    ~(c is now 5)
\end{lstlisting}

\emph{ Increment the counter by 1 }
\begin{lstlisting}
  c=4; let c+=1;     ~(c is now 5)
\end{lstlisting}
  
\emph{ Decrement the counter by 1 }
\begin{lstlisting}
  c=4; let c-=1;     ~(c is now 3)
\end{lstlisting}
 

  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ comparing numbers, the tests are  }} \\
  \hline

  \texttt{ -eq } & Equal to \\ 

  \texttt{ -ne } & Not equal to  \\ 

  \texttt{ -lt } & Less than $<$ \\ 

  \texttt{ -le } & Less than or equal $<$= \\ 

  \texttt{ -gt } & Greater than $>$ \\ 

  \texttt{ -ge } & Greater than or equal $>$= \\ 

    \hline
    \end{tabular}
    \end{center}
\section{String Variables}

\emph{ Echo the text 'linux' in reverse  }
\begin{lstlisting}
  echo linux | rev
\end{lstlisting}

\emph{ Reverse the order of the characters in a string }
\begin{lstlisting}
  s='tree'; s=$(echo $s | rev); echo $s
\end{lstlisting}

\emph{ Check if a the the word 'madam' is a palindrome }
\begin{lstlisting}
  s='madam'; [ "$s" == "$(echo $s | rev)" ] && echo palindrome! || echo nope
\end{lstlisting}

\subsection{Analysing Strings}

\emph{ Test if a variable consists only of white space or nothing }
\begin{lstlisting}
  i="  "; if [ -z $i ]; then echo "empty"; fi
\end{lstlisting}
\begin{lstlisting}
  i="  "; [ -z $i ] && echo "empty"            ~(the same)
\end{lstlisting}

\emph{ Test for an empty string variable }
\begin{lstlisting}
  i="  x"; test ! -z $i && echo "not empty"   ~(prints "not empty")
\end{lstlisting}

  Both of these scripts above will print 'empty'

\emph{ Test if the string variable \$s contains the text 'tree' }
\begin{lstlisting}
  s='this tree'; if [[ $s == *tree* ]]; then echo "yes"; fi
\end{lstlisting}

\emph{ Print 'has a dot' if the string contains a full stop }
\begin{lstlisting}
  s='one.two'; if [[ $s == *.* ]]; then echo "has a dot"; fi
\end{lstlisting}
\begin{lstlisting}
  s='one.two'; [[ $s == *.* ]] && echo "has a dot"
\end{lstlisting}

\emph{ Print 'no dot' if the variable 's' contains no full stop  }
\begin{lstlisting}
  s='onetwo'; [[ $s != *.* ]] && echo "no dot"
\end{lstlisting}

\emph{ Display the number of characters in a string  }
\begin{lstlisting}
  aa=bbbb; echo ${#aa}   ~(prints 4) 
\end{lstlisting}

\subsection{String Case}

\emph{ Convert the word 'tree' to uppercase }
\begin{lstlisting}
  echo tree | tr '[:lower:]' '[:upper:]'
\end{lstlisting}
 
\emph{ Convert the string variable 's' to upper case }
\begin{lstlisting}
  s="the grass"; s=$(echo $s | tr '[:lower:]' '[:upper:]');echo $s
\end{lstlisting}

\subsection{Comparing Strings}

\emph{ Test if 2 strings are not the same }
\begin{lstlisting}
  if test "$a" != "$b" ; then echo 'not the same'; fi
\end{lstlisting}
\begin{lstlisting}
  if [ "$a" != "$b" ]; then echo 'not the same'; fi  ~(another way)
\end{lstlisting}
  
\emph{ Test if 2 strings are the same or different }
\begin{lstlisting}
  if test "$a" = "$b" ; then echo 'the same'; fi
\end{lstlisting}

\subsection{Splitting Strings}

\emph{ Split the string 'aa bb cc' on whitespace (prints 'bb') }
\begin{lstlisting}
  ARRAY=(aa bb cc);echo ${ARRAY[1]}  
\end{lstlisting}

\emph{ Split the string ``aa bb cc'' into 3 variables }
\begin{lstlisting}
  read v1 v2 v3 < <(echo aa bb cc); echo $v2
\end{lstlisting}

\emph{ Split a string into an array using commas as delimiter }
\begin{lstlisting}
  s='a,b,c'; a=(${s//,/ }); echo ${a[1]}
\end{lstlisting}
  
\begin{lstlisting}
  a=xyzxyz; a=${a//x/q}; echo $a;     ~(prints qyzqyz)
\end{lstlisting}
\begin{lstlisting}
  ARRAY=(aa bb cc);echo ${ARRAY[1]}  
\end{lstlisting}

\subsection{Whitespace}

\emph{ Show whitespace in a visible manner }
\begin{lstlisting}
  echo -e "\t\n" | cat -vte
\end{lstlisting}

\subsection{Replacing And Substituting Strings}

\emph{ Replace the first "x`` in the string with a ''q" }
\begin{lstlisting}
  a=xyzxyz; a=${a/x/q}; echo $a;     ~(prints qyzxyz)
\end{lstlisting}

\emph{ Replace all occurrences of 'x' in the string 'a' }
\begin{lstlisting}
  a=xyzxyz; a=${a//x/q}; echo $a;     ~(prints qyzqyz)
\end{lstlisting}

\emph{ Replace all occurrences of 'a' in a string with the word 'the' }
\begin{lstlisting}
  s="a book. a tree"; s=${s//a/the}; echo $s;  
\end{lstlisting}

\emph{ Replace all occurrences of '.' in a string with a '/' slash character }
\begin{lstlisting}
  s="a.b.c"; s=${s//./\/}; echo $s;  
\end{lstlisting}

\subsection{Substrings Of Strings}

\emph{ Extract a substring from a string  }
\begin{lstlisting}
  s=abcde; echo ${s:1}   ~(prints bcde, the string "s" is not changed)
\end{lstlisting}

\begin{lstlisting}
  s=abcdefghi; echo ${s:3:3}   ~(prints def)
\end{lstlisting}

\emph{ Delete an exact match of one variable within another }
\begin{lstlisting}
  f=tree; r=re; f=${f/$r/}; echo $f   <: prints "te" :>
\end{lstlisting}
\begin{lstlisting}
  f=tree; r=re; f=${f##$r}; echo $f   <: the same :>
\end{lstlisting}

\emph{ Print only the first word of a sentence }
\begin{lstlisting}
  a="one two thre"; echo ${a%% *}
\end{lstlisting}

\emph{ Print only the last word in a sentence  }
\begin{lstlisting}
  foo="simple forth machine"; echo ${foo##* }   
\end{lstlisting}
  This prints 'machine'
  
\emph{ Strip all but the last word from a sentence  }
\begin{lstlisting}
  s="simple forth machine"; s=${s##* }; echo $s
\end{lstlisting}
  The variable 's' now has the text ``machine'' 
  
\emph{ Delete only the first match of a substring in a string  }
\begin{lstlisting}
  foo="this is a test"; echo ${foo#t}   ~(prints 'his is a test')
\end{lstlisting}

\emph{ Delete the shortest match starting from the left }
\begin{lstlisting}
  foo="this is a test"; echo ${foo#t*is}   ~(prints 'is a test')
\end{lstlisting}

\begin{lstlisting}
  s="12: this is a test"; echo ${s#t*t}
\end{lstlisting}

\emph{ Delete the longest match from the left }
\begin{lstlisting}
  foo="this is a test"; echo ${foo##t*is}   ~(prints 'a test')
\end{lstlisting}

\emph{ Deletes the last match of a substring in a string }
\begin{lstlisting}
  foo="this is a test"; echo ${foo%t}    ~(prints 'this is a tes')
\end{lstlisting}

\emph{ Delete the last 2 characters of a string }
\begin{lstlisting}
  foo="this is a test"; echo ${foo%??}    ~(prints 'this is a te')
\end{lstlisting}

\emph{ Deletes the shortest match from the end  }
\begin{lstlisting}
  foo="this is a test"; echo ${foo%t*st}    ~(prints 'this is a')
\end{lstlisting}

\emph{ Deletes the longest match from the end of the string variable }
\begin{lstlisting}
  foo="this is a test"; echo ${foo%%t*st}    ~(prints nothing)
\end{lstlisting}

\emph{ Remove the file name extension from a filename }
\begin{lstlisting}
  f=index.txt; f=${f%.txt}; echo $f  ~(prints 'index')
\end{lstlisting}
\begin{lstlisting}
  f=index.txt; mv f ${f%.txt}        ~(actually renames the file, careful)
\end{lstlisting}

  See http://tldp.org/LDP/abs/html/refcards.html for more patterns

\subsection{Concatenating String Variables}

  Joining 2 or more string variables together into one big
  string is known as ``concatenating''. 

\emph{ Append a string onto the end of a variable  }
\begin{lstlisting}
  m=aa; m+=bb; m+=cc; echo $m   ~(prints 'aabbcc')
\end{lstlisting}

  The above is probably a recent bash extension.

\emph{ Add the string ``tree'' to the end of a variable }
\begin{lstlisting}
  f=green; f=$f"tree"; echo $f    ~(prints "greentree")
\end{lstlisting}
\begin{lstlisting}
  f=green; f=${f}tree; echo $f    ~(the same)
\end{lstlisting}
\begin{lstlisting}
  f=green; f="${f}tree"; echo $f  ~(the same again)
\end{lstlisting}

\emph{ Join a string to the end of another string. }
\begin{lstlisting}
  f="this is";g=" a tree"; f=$f$g; echo $f  ~(prints "this is a tree")
\end{lstlisting}
\begin{lstlisting}
  f="this is";g=" a tree"; f="$f$g"; echo $f  ~(the same)
\end{lstlisting}

\emph{ Add 2 new-line characters to a string }
\begin{lstlisting}
  s=tree; s=$s$'\n'$'\n'; echo "$s"  ~(the quotes on the final $s ARE needed)
\end{lstlisting}

\subsection{Writing Strings To A File}

\emph{ Use echo -n ``\$data'' instead of echo \$data which 'squeezes' newlines }
\begin{lstlisting}
  echo -n "$data" > /home/username/data.txt
\end{lstlisting}

\subsection{Here Documents}

  The practice of creating a long string variable between a 
  start and an end label is called a 'here document'. This syntax
  exists in a number of programming languages (for example: PHP and Perl)
  Here documents are useful for printing or manipulating long multi-line
  strings.

\emph{ Use a 'here document', for long strings }
  \begin{lstlisting}
   cat << endx 
     This is a string with several lines.
     The end label can be anything, and can
     appear in the text as long as it doesnt start
     the line (like this 'endhere')
endx                  
  \end{lstlisting}
  (the end label 'endx' must be at the start of the line)

\emph{ Put commands and variables in a 'here document' (use \$(command)) }
  \begin{lstlisting}
    cat << ends
     The script name is $(basename $0)
ends
  \end{lstlisting}

\emph{ Make a 'here document' which does not expand variables or commands }
  \begin{lstlisting}
    cat <<'enddoc'
     commands such as $(pwd) will not be interpreted
     nor with variables such as $s
enddoc
  \end{lstlisting}
  (the trick is to use ``$<$$<$'LABEL''' instead of ``$<$$<$LABEL'')

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://forums.whirlpool.net.au/forum-replies-archive.cfm/759361.html}]
     A good comment about newline characters and bash
\end{description}

\emph{ Assign a here document to a bash variable }
  \begin{lstlisting}
   s="";while read -r line; do s=$s$'\n'$line; done <<zzz
   making a
   multi-line
   bash variable
zzz
  \end{lstlisting}

   in the script above, the ``read'' statement reads one
   line at a time from the here document and adds it
   onto the 's' variable with a newline character

\emph{ Put string substitutions in a ``here'' document  }
  \begin{lstlisting}
    f=text.html
    cat << eos
     The script is ${f/.html/}
eos
  \end{lstlisting}
  (this prints ``the script is text'')

\emph{ Pipe the output of a here document through another program }
  \begin{lstlisting}

    cat << eos | fmt
     The script name is $(basename $0)
eos
  \end{lstlisting}

\emph{ Run a tcl script as a here document }
  \begin{lstlisting}
    cat << eos | tclsh 
      puts "Seconds: [clock seconds]" 
eos
  \end{lstlisting}

\emph{ Loop through the lines a ``here document'' }
  \begin{lstlisting}
  while read -r s; do echo $s; done <<zzz
  first line
  second line
  3rd line
zzz
  \end{lstlisting}

\subsection{Interpolation In Strings}

  Interpolation means substituting variables within a string
  value with their values.

\emph{ Insert the value (text) of the variable 'v' in a string }
\begin{lstlisting}
  v=green; echo "The grass is $v"
\end{lstlisting}
  ( this prints ``The grass is green'' )
  
  Bash will generally 'interpolate' variables which are inserted with
  double-quoted (") strings. Interpolation is as idea which also
  occurs in perl, and other scripting languages.

\emph{ Stop a variable from interpolating with ?\$ }
\begin{lstlisting}
  v=5; echo "\$v is $v"
\end{lstlisting}
 
\emph{ String interpolation works with array values as well }
\begin{lstlisting}
  area[5]=bb; echo "The contents of area[5] is ${area[5]}."
\end{lstlisting}

\emph{ A complex example of interpolation using eval }
\begin{lstlisting}
  a=b; eval $(echo "echo \"this is xx\"" | sed 's/xx/$a/')
\end{lstlisting}
\begin{lstlisting}
  a=b; eval $(echo "echo this is xx" | sed 's/xx/$a/')    ~(also works)
\end{lstlisting}
\begin{lstlisting}
  export a=b; echo "echo this is xx" | sed 's/xx/$a/' | bash  ~(also)
\end{lstlisting}

  All 3 examples above do the same thing. But the last requires the
  'export' statement to make the 'a' variable available to all
  subprocesses. This is because the 'bash' command begins a new process.

\emph{ A simple 'templating' technique using interpolation }
\begin{lstlisting}
  echo -e 'todays \ndate \nis <date>' | (echo 'cat << EE';sed 's/<date>/$(date)/g'; echo 'EE') | bash 
\end{lstlisting}

  The text '$<$date$>$' in the input stream gets replaced by todays
  date. This is useful when the input-stream comes from a file.

\emph{ Use the technique above to substitute the date into the template }
\begin{lstlisting}
  cat template | (echo 'cat << EE';sed 's/<date>/$(date)/g'; echo 'EE') | bash 
\end{lstlisting}

\section{Date Variables}

\emph{ Check if a date is valid, even a date within a leap year- not BSD ?? }
\begin{lstlisting}
  date -d2009-05-18 > /dev/null 2>&1 ; echo $?
\end{lstlisting}
 
\emph{ Another date validation but not BSD unix  }
\begin{lstlisting}
  date -d2009-02-33 > /dev/null 2>&1 ; [ $? ] && echo valid || echo invalid
\end{lstlisting}

\emph{ Display a millisecond time difference  }
\begin{lstlisting}
  s=$(echo "scale=3; $(date +%s.%N)-$(date +%s.%N)" | bc);  echo ${s%??????}
\end{lstlisting}

\emph{ Display seconds and milliseconds since 1970 (gnu date only) }
\begin{lstlisting}
  s=$(date +%s.%N);  echo ${s%??????}
\end{lstlisting}

\section{Arrays}
  
  Bash arrays are 0-based, that is the first element of an array
  'list' is 'list[0]' not 'list[1]' (as in Ms Visual Basic)

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://tldp.org/LDP/abs/html/arrays.html}]
     some information about bash arrays.
\end{description}

\emph{ Display the fifth file in the current folder }
\begin{lstlisting}
  a=($(ls)); echo ${a[5]}
\end{lstlisting}

\emph{ Display the file which has been most recently modified in the folder  }
\begin{lstlisting}
  a=($(ls -t)); echo ${a[0]}
\end{lstlisting}

\emph{ Display a random file in the current folder }
\begin{lstlisting}
  a=($(ls)); echo ${a[$RANDOM%${#a}]}
\end{lstlisting}

\emph{ Echo each element of a comma delimited array. }
\begin{lstlisting}
  echo one,two,three | xargs -d, -I{} echo "{}"
\end{lstlisting}

\subsection{Declaring Arrays}

  In the bash shell, it is normally not necessary to declare variables
  (that is, state what type a variable is- whether a string, an integer, or
  an array). But it may be advantageous in some cases.

\emph{ Declare an array variable 'list' explicitly }
\begin{lstlisting}
  declare -a list
\end{lstlisting}

\emph{ Explicitly un-declare an array 'aa' }
\begin{lstlisting}
  unset -v aa
\end{lstlisting}

\subsection{Initialising Arrays}

\emph{ Initialize an array variable called 'list' }
\begin{lstlisting}
  list=(ant dog cat)   
\end{lstlisting}
  
  the element list[0] is 'ant' 
  the element list[1] is 'dog' ...

\emph{ Assign values to the 4th and 7th elements of the array 'area' }
\begin{lstlisting}
  area=([4]=hobart [7]=brunie)
\end{lstlisting}

\emph{ Make a new array 'files' from the current folder and display the 3rd  }
\begin{lstlisting}
  files=( *.txt ); echo ${files[2]}
\end{lstlisting}

\emph{ Assign the lines of a text file to an array (1 line per element)  }
\begin{lstlisting}
  ls -thor>t.txt; IFS=$'\n' aa=($(<t.txt)); echo "3rd=${aa[3]}"
\end{lstlisting}

\emph{ The same as above but IFS may have to be reset later }
\begin{lstlisting}
  ls -thor>t.txt; IFS=$'\n'; aa=($(<t.txt)); echo "3rd=${aa[3]}"
\end{lstlisting}

\emph{ Assign the words of a text file to an array (1 word per element)  }
\begin{lstlisting}
  cat /usr/share/dict/words>t.txt; aa=($(<t.txt));echo "100th=${aa[100]}"
\end{lstlisting}

\emph{ Create a new array and display all the elements  }
\begin{lstlisting}
  list=( *.txt ); echo ${list[@]}
\end{lstlisting}
\begin{lstlisting}
  list=(*.txt); echo ${list[*]}      ~(also works)
\end{lstlisting}

\emph{ Define the elements of an array over multiple lines  }
  \begin{lstlisting}
    list=("a dog"
     cat "a tree")
     echo ${list[0]}
  \end{lstlisting}

\emph{ Define the elements of an array over multiple lines  }
  \begin{lstlisting}
    list=(
     "a dog"
     cat "a tree"
    )
    echo ${list[0]}
  \end{lstlisting}

\subsection{Big Arrays}

\emph{ Load a very large array from the dictionary file  }
\begin{lstlisting}
  aa=($(cat /usr/share/dict/words)); echo ${aa[1000]}
\end{lstlisting}

  Since the standard unix dictionary may contain more than 200000 words
  the line above gives you an idea of how many elements a bash 
  array may contain and how fast it takes to load that many elements

\emph{ See how long it takes to load a big array }
  \begin{lstlisting}
   f=/usr/share/dict/words; 
   time aa=($(cat $f));
   echo The array has ${#aa[@]} elements
  \end{lstlisting}

\subsection{Initializing Arrays From Files}

\emph{ Assign the lines of a text file to an array (1 line per element)  }
\begin{lstlisting}
  ls -thor > t.txt; IFS=$'\n'; aa=($(<t.txt)); echo "3rd=${aa[3]}"
\end{lstlisting}

  Note the judicious use of IFS, since otherwise the text of 
  the file 't.txt' would be split into words rather than 
  lines.

\emph{ Assign the lines of a text file to an array (1 line per element)  }
  \begin{lstlisting}
    ls -thor > t.txt    
    IFS=$'\n'
    aa=($(cat t.txt))
    echo "3th element=${aa[3]}"
  \end{lstlisting}

\emph{ Mapfile is also supposed to work, but not for me }
\begin{lstlisting}
  echo -e "a b\nc d\ne f" | mapfile -n 0 aa; echo ${aa[*]}
\end{lstlisting}
\begin{lstlisting}
  echo -e "a b\nc d\ne f" | mapfile aa; echo ${aa[*]}
\end{lstlisting}
\begin{lstlisting}
  echo -e "a b\nc d\ne f" | mapfile ; echo ${mapfile[*]}
\end{lstlisting}

\emph{ Another way to read the lines of 'test.txt' into an array }
  \begin{lstlisting}
  i=1
  while read line
  do
      array[$i]="$line"
      echo "${array[$i]}"
      ((i++))
  done < test.txt
  \end{lstlisting}

\subsection{Initializing With Command Output}

\emph{ Assign the lines of a text file to an array (1 line per element)  }
\begin{lstlisting}
  IFS=$'\n' aa=($(ls -thor)); echo "4th element=${aa[3]}"
\end{lstlisting}

  The command above is the simplest way to set the elements of
  an array to be the lines of the output of some command. But without
  the IFS variable being set, the elements of the array would be 
  initialised to the 'words' (space separated) of the command output,
  not the lines. Notice how there is no semi-colon after the 
  setting the IFS variable, this means that we only change the value
  of the variable for this one command and not subsequent commands.

\emph{ We could also do this as follows but would have to reset IFS }
\begin{lstlisting}
  IFS=$'\n'; aa=($(ls -thor)); echo "4th element=${aa[3]}"
\end{lstlisting}

\emph{ Another technique to read lines into an array  }
  \begin{lstlisting}
  i=1
  ls -thor | while read line
  do
    array[$i]="$line";
    echo ${array[$i]}
    ((i++))
  done
  \end{lstlisting}

\emph{ Read disk usage figures into an array, line by line  }
  \begin{lstlisting}
    IFS=$'\n' aa=($(du -sh *))
    echo "3th element=${aa[3]}"
  \end{lstlisting}

\emph{ Another more complicated way to do the same thing  }
  \begin{lstlisting}
  du -sh * | while read line
  do
    aa[${#aa[@]}]="$line"
    echo "${aa[$((${#aa[*]}-1))]}"
  done
  \end{lstlisting}

\subsection{Copying Arrays}

\emph{ Make a copy of array 'aa' in 'bb'  }
\begin{lstlisting}
  aa=(1 2 3); bb=( "${aa[@]}" ); echo "${bb[*]}"
\end{lstlisting}

  This technique may not work of the array 'aa' is 'sparse', which
  means that only some values have been set.

\emph{ Make a copy of an array. }
\begin{lstlisting}
  array2="${array1[@]}"
\end{lstlisting}

\emph{ Adding an element to an array. }
\begin{lstlisting}
  aa= "${aa[@]}" "new element" )
\end{lstlisting}
\begin{lstlisting}
  cc=( 1 2 ); cc[${#cc[*]}]="three"; echo ${cc[*]}
\end{lstlisting}

  These fail for sparse arrays

\subsection{Assigning Values}

\emph{ Set the first element of the array 'list' to the text 'horse' }
\begin{lstlisting}
  list[0]=horse
\end{lstlisting}

\emph{ Set the 2nd element of the array 'list' to the text 'fast horse' }
\begin{lstlisting}
  list[1]="fast horse"  ~( use quotes to allow value white-space)
\end{lstlisting}

\emph{ Assign a list of files to an array }
\begin{lstlisting}
  list=( *.txt ); ~( list is an array and not a string )
\end{lstlisting}

\subsection{Modifying Arrays}

\emph{ Create an array and replace all 's' characters with 'S' in all elements  }
\begin{lstlisting}
  list=(*.txt); echo ${list[@]//s/S}
\end{lstlisting}

\emph{ Replace all 's' characters with 'S' in an array }
\begin{lstlisting}
  list=(*.txt); list=(${list[@]//s/S}); echo ${list[@]}
\end{lstlisting}

\emph{ Replace the first character of all array elements with an '.' }
\begin{lstlisting}
  list=(*.txt); list=(${list[@]/?/.}); echo ${list[@]}
\end{lstlisting}

\subsection{Accessing Array Values}

\emph{ Display the first element of an array variable 'list' }
\begin{lstlisting}
  echo ${list[0]}  ~( not '$list[0]' which prints 'one[0]' )
\end{lstlisting}
\begin{lstlisting}
  echo $list       ~( this also displays only the 1st element ) 
\end{lstlisting}

\emph{ Display the 4th element of a bash array variable 'list' }
\begin{lstlisting}
  echo ${list[3]}
\end{lstlisting}

\emph{ Use string 'interpolation' to insert the value of an array in text }
\begin{lstlisting}
  echo "The Contents of area[5] is ${area[5]}."
\end{lstlisting}

\emph{ Display all the values of the array 'list' }
\begin{lstlisting}
  echo ${list[*]}
\end{lstlisting}
\begin{lstlisting}
  echo ${list[@]}   ~(there is some subtle difference, but what?)
\end{lstlisting}

\subsection{Array Length}

\emph{ Display the number of elements in an array }
\begin{lstlisting}
  list=(one 2 three four);  echo ${#list[@]}
\end{lstlisting}

\emph{ Display the last element in an array  }
\begin{lstlisting}
  a=(one 2 three four);  echo ${a[$((${#a[@]}-1))]}
\end{lstlisting}

\emph{ Display the oldest file in the current folder  }
\begin{lstlisting}
  a=($(ls -t));  echo ${a[$((${#a[@]}-1))]}
\end{lstlisting}

\subsection{Subsets Of Arrays}

\emph{ Print the 2nd and remaining characters of the 1st element }
\begin{lstlisting}
  echo ${list:1} ~(if list[0]=big this prints 'ig')
\end{lstlisting}

\emph{ Display the 2nd, 3rd and 4th elements of the array 'list' }
\begin{lstlisting}
  echo ${list[@]:1:3}   
\end{lstlisting}

\emph{ Display the 2nd and all remaining elements of the array 'list' }
\begin{lstlisting}
  echo ${list[@]:1}   
\end{lstlisting}

\emph{ Display the 3rd, 4th and 5th characters of element 1 of 'list' }
\begin{lstlisting}
  echo ${list[0]:2:4}  ~( if list[0]=quick then prints 'ick' )
\end{lstlisting}
\begin{lstlisting}
  echo ${list:2:4}     ~( the same, [0] is assumed ) 
\end{lstlisting}

\emph{ Display the 2rd and 3rd characters of element 4 of 'list' }
\begin{lstlisting}
  echo ${list[3]:1:2}  ~( if list[3]=water then prints 'at' )
\end{lstlisting}

\emph{ Bookmark folder for quick changing }
\begin{lstlisting}
  cdargs
\end{lstlisting}

\subsection{Looping Through Arrays}

\emph{ Loop through an array properly }
  \begin{lstlisting}
   names=( "a dog" cat "a tree")
   for (( i = 0; i < ${#names[@]}; i++ ))
   do
     echo "element $i=${names[$i]}"
   done
  \end{lstlisting}

  note: theres no 'seq' on apple osx ! but you could use
  bash arithmetic expansion $\{$1..20$\}$ etc

\emph{ Loop through an array properly, one element at a time, not by words }
  \begin{lstlisting}
   aa=( "a dog" cat "a tree")
   for (( i = 0; i < ${#aa[@]}; i++ ))
   do
     echo "element $i=${aa[$i]}"
   done
  \end{lstlisting}

\emph{ Getting a dynamic array element list, tricky but works }
\begin{lstlisting}
  aa=("a b" c "d e"); eval "echo {1..${#aa[@]}}";
\end{lstlisting}

\emph{ A more tricky loop using bash globbing,  }
  \begin{lstlisting}
   aa=( "a dog" cat "a tree")
   for i in $(eval "echo {0..$((${#aa[@]}-1))}")
   do
     echo "element $i=${aa[$i]}"
   done
  \end{lstlisting}

\emph{ A more compact loop using braces instead of do/done  }
  \begin{lstlisting}
   aa=( "a dog" cat "a tree")
   for i in $(eval "echo {0..$((${#aa[@]}-1))}")
     { echo "$i=${aa[$i]}"; }
  \end{lstlisting}
 
\emph{ Bash arithmetic, which prints 11 }
\begin{lstlisting}
  a=12; a=$((a-1)); echo $a  
\end{lstlisting}

\emph{ Loop through an array properly with seq, but this is untested }
  \begin{lstlisting}
   aa=( "a dog" cat "a tree")
   for i in $(seq 0 $((${#aa[@]}-1))) 
   do
     echo "element $i=${names[$i]}"
   done
  \end{lstlisting}

\subsection{Looping Through Words Of Arrays}

  
\emph{ Loop through all the words in the array elements }
  \begin{lstlisting}
    list=( "a dog" cat "a tree")
    for f in ${list[@]}; do echo $f; done
    echo "list has ${#list[*]} elements"
  \end{lstlisting}

\emph{ Loop through all the words of elements of an array }
\begin{lstlisting}
  aa=(*.txt); for f in ${aa[@]}; do echo $f; done
\end{lstlisting}

  If the elements have spaces this may not be what you want

\emph{ Make an array from the disk usage and show the second element }
\begin{lstlisting}
  list=($(du -sh */)); echo ${list[1]}
\end{lstlisting}

\subsection{More Arrays}

\emph{ Load a file into an array 'aa' (but this is word by word, not by line) }
\begin{lstlisting}
  aa=(`cat "$filename"`) 
\end{lstlisting}

\emph{ Define an array with 3 strings, some with spaces in them }
\begin{lstlisting}
  list=("a dog" cat "a tree"); echo ${list[@]}
\end{lstlisting}

\emph{ Use 'string interpolation' to show the 2nd element of and array }
\begin{lstlisting}
  list=("a dog" cat "a tree"); echo "2nd element=${list[1]}"
\end{lstlisting}

\emph{ Add an element to an array using 'eval' and a string }
\begin{lstlisting}
  aa=(one 2 three); eval "aa[3]='a frog'"; echo ${aa[3]}
\end{lstlisting}

\emph{ Assign an array element with spaces }
\begin{lstlisting}
  aa[2]="a frog"; echo ${aa[2]}
\end{lstlisting}

\emph{ Another 2 level evaluation technique for defining an array element }
\begin{lstlisting}
  aa=(one 2 three); eval $(echo "aa[3]='a frog'"); echo ${aa[3]}
\end{lstlisting}

\emph{ What does this do }
\begin{lstlisting}
  aa=(*.txt); s="{${aa[@]}}"; s=${s// /,}"aa"; echo $s
\end{lstlisting}

\section{Reading Line By Line}

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://www.somebits.com/weblog/tech/bash-read-command.html}]
    good hints about reading with read
\end{description}

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://codesnippets.joyent.com/posts/show/1899}]
    another technique for reading lines into an array
    a knowledgeable post.
\end{description}

\emph{ Use 'mapfile' as another way to read into arrays }
\begin{lstlisting}
  ls -thor | mapfile aa; echo ${#aa[@]}
\end{lstlisting}

\section{Using Jot For Example Data}

\emph{ Make some random data, good .... }
\begin{lstlisting}
  jot
\end{lstlisting}

\emph{ Prints 21 decimal numbers increasing evenly from -1 to 1. }
\begin{lstlisting}
  jot 21 -1 1.00
\end{lstlisting}

\emph{ Generate the ascii character set, one character per line }
\begin{lstlisting}
  jot -c 128 0 | less
\end{lstlisting}

\emph{ Generate the strings 'xaa' through 'xaz'  }
\begin{lstlisting}
  jot -w xa%c 26 a | less
\end{lstlisting}

\emph{ Generate 20 random 8-letter strings }
\begin{lstlisting}
  jot -r -c 160 a z | rs -g 0 8
\end{lstlisting}

\emph{ Generate an infinite number of yes's each on a new line }
\begin{lstlisting}
  jot -b yes 0
\end{lstlisting}

\emph{ Generate thirty 'ed' substitution commands applying to lines 2, 7, 12, etc }
\begin{lstlisting}
  jot -w %ds/old/new/ 30 2 - 5
\end{lstlisting}

\emph{ The stuttering sequence 9, 9, 8, 8, 7, etc. can be produced }
\begin{lstlisting}
  jot - 9 0 -.5
\end{lstlisting}

\emph{ Create a file containing exactly 1024 bytes }
\begin{lstlisting}
  jot -b x 512 > block
\end{lstlisting}

\emph{ Set tabs four spaces apart starting at column 10, ending in column 132 }
\begin{lstlisting}
  expand -`jot -s, - 10 132 4`
\end{lstlisting}

\emph{ Print all lines 80 characters or longer, }
\begin{lstlisting}
  grep $(jot -s "" -b . 80)
\end{lstlisting}

\section{Paste}
  
\emph{ List the files in the current directory in three columns: }
\begin{lstlisting}
  ls | paste - - -     ~(tab delimited)
\end{lstlisting}
\begin{lstlisting}
  ls | xargs -L3       ~(space delimited)
\end{lstlisting}
 
\emph{ Paste corresponding lines of 'f1' \& 'f2' into 2 columns separated by ',' }
\begin{lstlisting}
  jot -w tree 10 > f1; jot -w leaf 10 > f2; paste -d, f1 f2
\end{lstlisting}

\emph{ Show the sub-folders in a 3 column output separated by commas ','  }
\begin{lstlisting}
  ls -d */ | paste -d',' - - -
\end{lstlisting}

\emph{ Combine pairs of lines from a file into single lines: }
\begin{lstlisting}
  jot -w tree 20 > f; paste -s -d '\t\n' f
\end{lstlisting}

\emph{ Combine pairs of lines from a file into comma delimited lines }
\begin{lstlisting}
  jot -w tree 20 > f; paste -s -d ',\n' f
\end{lstlisting}

  The jot is just used to create some example data

\emph{ Number the lines in a file, similar to 'nl' }
\begin{lstlisting}
  sed = myfile | paste -s -d '\t\n' - -
\end{lstlisting}

\emph{ Create a colon-separated list of folders named bin, suitable for use in the PATH environment variable: }
\begin{lstlisting}
  find / -name bin -type d | paste -s -d : -
\end{lstlisting}
 

  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ other text data tools }} \\
  \hline

 \texttt{ lam } & Join file lines (how is this different from 'paste'?) \\ 

 \texttt{ join } & A text relational database tool \\ 

    \hline
    \end{tabular}
    \end{center}
\section{End Paste}

\section{Extended Globbing}

 'Globbing' is the process of expanding certain special characters
 (often called 'wildcards') into a list of files, or into a pattern
 to match against another string.

\emph{ Activate special wildcard 'globbing' in scripts }
\begin{lstlisting}
  shopt -s extglob
\end{lstlisting}

\emph{ Remove all files except ones with names ending in .jpg }
\begin{lstlisting}
  shopt -s extglob; rm !(*.jpg)
\end{lstlisting}

\emph{ Remove all files except *.jpg and *.gif and *.png }
\begin{lstlisting}
  shopt -s extglob; rm !(*.jpg|*.gif|*.png)
\end{lstlisting}

\emph{ Trim leading and trailing whitespace from a variable (needs extglob) }
\begin{lstlisting}
  x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}
\end{lstlisting}

\emph{ Show visible the characters used to split strings in globbing }
\begin{lstlisting}
  echo "$IFS" | cat -vte
\end{lstlisting}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ extglob extended patterns }} \\
  \hline

 \texttt{ ?(pattern-list) } & Matches zero or one occurrence of the given patterns. \\ 

 \texttt{ *(pattern-list) } & Matches zero or more occurrences of the given patterns. \\ 

 \texttt{ +(pattern-list) } & Matches one or more occurrences of the given patterns. \\ 

 \texttt{ @(pattern-list) } & Matches one of the given patterns. \\ 

 \texttt{ !(pattern-list) } & Matches anything except one of the given patterns. \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Delete the second field in a ':' delimited variable }
\begin{lstlisting}
  shopt -s extglob; a=one:two:3; a=${a/:+([^:])}; echo $a
\end{lstlisting}

\emph{ Set the ifs variable to only new lines }
\begin{lstlisting}
  IFS=$'\n'
\end{lstlisting}

 The line about seems mysterious and cryptic, but has an enormous use
 in many situations. If you ever want to loop through the lines of
 some output, using 'for' or 'select' then you need to set the IFS 
 variable first. This is because IFS determines how input will be
 split into 'tokens' when iterating through some text will 'for' 
 etc. By default 'for' and 'select' will use IFS to split all output
 on all whitespace (not just new-lines)

\begin{lstlisting}
  IFS=$'\n'; PS3="Enter a number: "; select f in $(ls -la);do vim $f; break; done
\end{lstlisting}
\begin{lstlisting}
  PS3="Enter a number: "; select f in $(ls -la);do vim $f; break; done
\end{lstlisting}

\section{String Substitution}

 see the 'extglob' shell option for better bash patterns
 
\begin{lstlisting}
  If $sub matches at front end of $s, substitute $replacement for $sub
\end{lstlisting}
\begin{lstlisting}
  ${s/#sub/replacement}
\end{lstlisting}

\emph{ If \$substring matches back end of \$string, substitute \$replacement for \$substring. }
\begin{lstlisting}
  ${string/%substring/replacement}
\end{lstlisting}

\subsection{Prefix Deletion And Substitution}

 The \$$\{$x\#..$\}$ operator is equivalent to a regular expression such
 as /\^{}.../ 

 In bash patterns '?' is equivalent to /./ in a regular expression
 and '*' is equivalent to /.*/ With \$$\{$x\#$\}$ '*' is not greedy but
 with \$$\{$x\#\#$\}$ '*' is greedy
 
\emph{ Delete up to and including the 1st colon in a string variable }
\begin{lstlisting}
  s="one:two:3:four"; s=${s#?*:}; echo $s      ~(prints 'two:3:four')
\end{lstlisting}
\begin{lstlisting}
  s="one:two:3:four"; s=${s#[^:]*:}; echo $s   ~(the same effect)
\end{lstlisting}

\emph{ Delete up to and including the last colon in a string variable }
\begin{lstlisting}
  s="one:two:3:four"; s=${s##?*:}; echo $s      ~(prints 'four')
\end{lstlisting}

 
\begin{lstlisting}
  s="one:two:3:four"; s=${s#*:}; echo $s      ~(prints 'four')
\end{lstlisting}

\subsection{Suffix Deletion And Substitution}

 The \$$\{$x\%...$\}$ operator is equivalent to a /...\$/ regular expression
 pattern. In this context the '*' operator is not greedy

\emph{ Delete from the last ':' colon to the end of a string variable  }
\begin{lstlisting}
  s="one:two:3:four"; s=${s%:?*}; echo $s     ~(prints 'one:two:3')
\end{lstlisting}
\begin{lstlisting}
  s="one:two:3:four"; s=${s%:[^:]*}; echo $s  ~(the same effect)
\end{lstlisting}

\subsection{String Deletion And Substitution}

  Modern versions of Bash allow for some very capable string 
  substitution. In some cases these techniques may replace what was
  formerly done with a 'sed' command.

  Note the \$$\{$x/..$\}$ is a 'greedy' matching operator when used with
  the '*' wildcard character. It will match as much text as it can.

\emph{ Delete everything after the 1st colon character (not including ':') }
\begin{lstlisting}
  a=name:david; a=${a/:*/:}; echo $a       ~(this prints 'name:')
\end{lstlisting}

\emph{ Delete everything after the 1st colon character (including the ':') }
\begin{lstlisting}
  a=name:ben; a=${a/:*}; echo $a      ~(prints 'name')
\end{lstlisting}
\begin{lstlisting}
  a=name:ben; a=${a/:*/}; echo $a     ~(the same, but unnecessary)
\end{lstlisting}

\emph{ Delete all fields except the 1st and last in a ':' colon delimited variable }
\begin{lstlisting}
  a=name:alex:john:fox; a=${a/:*:/:}; echo $a    ~(prints 'name:fox')
\end{lstlisting}

\begin{lstlisting}
  a=6:vim:42:emacs; a=${a/:[^:]*/:}; echo $a     ~(prints 'name:fox')
\end{lstlisting}

\begin{lstlisting}
  a=6:b:j:fox; a=${a/:[^:]:/:}; echo $a    ~(prints 'name:fox')
\end{lstlisting}

  
\emph{ Delete everything except the 1st word in a bash variable }
\begin{lstlisting}
  a="why is this so"; a=${a/[ ]*/}; echo $a    ~(prints 'why')
\end{lstlisting}
\begin{lstlisting}
  a="why is this so"; a=${a/ *}; echo $a      ~(the same, prints 'why')
\end{lstlisting}

\emph{ Delete all words in a bash variable except the 1st and the last  }
\begin{lstlisting}
  a="why is this so"; a=${a/[ ]*[ ]/ }; echo $a    ~(prints 'why so')
\end{lstlisting}
\begin{lstlisting}
  a="why is this so"; a=${a/ * / }; echo $a        ~(the same)
\end{lstlisting}

\emph{ Delete everything after a '.' or a ':' (which ever comes first) }
\begin{lstlisting}
  a=google.net:8080; a=${a/[:.]*}; echo $a      ~(prints 'google')
\end{lstlisting}
\begin{lstlisting}
  a=google.net:8080; echo $a | sed 's/[.:].*//'  ~(the same, with sed)
\end{lstlisting}
 
\emph{ Delete everything after the first lowercase roman letter }
\begin{lstlisting}
  a=12A:boat; a=${a/[a-z]*}; echo $a          ~(prints '12A:')
\end{lstlisting}

\emph{ Delete all text after the 1st roman letter in a bash variable }
\begin{lstlisting}
  a=12A:boat; a=${a/[a-zA-Z]*}; echo $a    ~(prints '12')
\end{lstlisting}

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://www.hypexr.org/bash_tutorial.php\#colors}]
    some interesting notes about bash tools
\end{description}

\emph{ Suppress error messages }
\begin{lstlisting}
  ls 2>/dev/null
\end{lstlisting}

\emph{ Pipe the output of 2 commands (on separate lines) to 'less' }
  \begin{lstlisting}
    (ls;
      pwd) | less
  \end{lstlisting}

\emph{ Another multi-line grouping that works, note the final ';' semicolon }
  \begin{lstlisting}
   { ls; 
     pwd; } | less
  \end{lstlisting}

\emph{ A function to search some book files for recipes or descriptions }
  \begin{lstlisting}

  function sr {
    if [ -z "$1" ]; then
      echo "usage: $FUNCNAME <search-term> [<search-term>] [<search-term>]"
      echo " - searches the book files for recipes with the search term(s)"
      echo " - the search term(s) can be in the recipe or the recipe description"
      echo "   or multiple search terms "
      return 1;
    fi
    ( find ~/sf/htdocs/books -name '*-book.txt' | xargs grep -hA2 "^ *\*.*$1.*$2.*$3" ;
  find ~/sf/htdocs/books -name '*-book.txt' | xargs grep -hB2 "^ *>>.*$1.*$2.*$3") | less
  }

 \end{lstlisting}

\section{If Else}

\emph{ An if elif statement }
  \begin{lstlisting}
    if something ; then
      do_stuff
    elif something_else ; then
      do_other_stuff
    elif [... ] ; then
      echo "ss" 
    else
      :
    fi
  \end{lstlisting}

\emph{ Use a ':' to do nothing in an if else clause }
  \begin{lstlisting}
   if [ -z "$x" ]; then
     :
   else
     einfo "Not"
   fi
  \end{lstlisting}


\section{A Big List Of File Tests}

  -a file        Exists (use -e instead)
  -b file        Exists and is a block special file
  -c file        Exists and is a character special file
  -d file        Exists and is a directory
  -e file        Exists
  -f file        Exists and is a regular file
  -g file        Exists and is set-group-id
  -h file        Exists and is a symbolic link
  -k file        Exists and its sticky bit is set
  -p file        Exists and is a named pipe (FIFO)
  -r file        Exists and is readable
  -s file        Exists and has a size greater than zero
  -t fd  Descriptor fd is open and refers to a terminal
  -u file        Exists and its set-user-id bit is set
  -w file        Exists and is writable
  -x file        Exists and is executable
  -O file        Exists and is owned by the effective user id
  -G file        Exists and is owned by the effective group id
  -L file        Exists and is a symbolic link
  -S file        Exists and is a socket
  -N file        Exists and has been modified since it was last read

\subsection{Substrings}

\emph{ Remove the shortest match from the front of all array elements  }
  \begin{lstlisting}
    echo ${list[@]#f*r} 
    if $list was 'forr five afur' before then afterwards
    'r five a'
  \end{lstlisting}

\emph{ Remove the longest match from front of all elements of 'list' }
\begin{lstlisting}
  echo ${list[@]##t*e} 
\end{lstlisting}
\begin{lstlisting}
  'list' before: trepef four atrapee
\end{lstlisting}
\begin{lstlisting}
  'list' after:  f four a 
\end{lstlisting}

\emph{ Remoe the shortest match from back of all elements  }
\begin{lstlisting}
  echo ${list[@]%h*e}  
\end{lstlisting}

\emph{ Remove the longest match from back of all elements of the array }
\begin{lstlisting}
  echo ${list[@]%%t*e}
\end{lstlisting}

\subsection{Replacing Substrings In Array Elements}

\emph{ Replace the first occurrence of 'fiv' with 'XYZ' in all elements }
\begin{lstlisting}
  echo ${list[@]/fiv/XYZ}   
\end{lstlisting}

\emph{ Replace all occurrences of 'iv' with 'YY' in all elements }
\begin{lstlisting}
  echo ${list[@]//iv/YY} 
\end{lstlisting}

\emph{ Delete all occurrences of 'fi' in all elements of the array }
\begin{lstlisting}
  echo ${list[@]//fi/} 
\end{lstlisting}

\emph{ Replace occurrences of 'e' with the output of a function 'rep' }
  \begin{lstlisting}
    rep() {
      echo -n "!!!"
    }
    #echo ${list[@]/%e/$(rep)}
    echo ${list[@]/e/$(rep)}
  \end{lstlisting}

\subsection{Calculating With Arrays}

\emph{ Add the 2 values of an array and assign to another }
\begin{lstlisting}
  area[5]=`expr ${area[11]} + ${area[13]}`
\end{lstlisting}
\begin{lstlisting}
  area[5]=$(expr ${area[11]} + ${area[13]})  ~(the same?)
\end{lstlisting}

\subsection{Array Length}

\emph{ Display the length of the array (or the index of last value) }
\begin{lstlisting}
  echo ${#list}         
\end{lstlisting}
\begin{lstlisting}
  echo ${#list[*]}    ~(the same, but possibly very different)
\end{lstlisting}

\emph{ Print the length of the string of the 1st element of array 'list' }
\begin{lstlisting}
  echo ${#list[0]} ~( if list[0]=tree this prints '4')
\end{lstlisting}

\emph{ Print the length of the string of the 3st element of array 'list' }
\begin{lstlisting}
  echo ${#list[2]} ~( if list[2]=big this prints '3')
\end{lstlisting}

\subsection{Joining Arrays}

\emph{ Join the elements of an array with ',' commas }
\begin{lstlisting}
  a=(a b c); s=$IFS; IFS=","; new="${a[*]}"; IFS=$s; echo $new
\end{lstlisting}

\emph{ Another way to join an array }
  \begin{lstlisting}
    #/!bin/bash
    foo=('foo bar' 'foo baz' 'bar baz')
    bar=$(printf ",%s" "${foo[@]}"); bar=${bar:1}
    echo $bar
  \end{lstlisting}

\section{Functions}

  Function definitions can be placed in the ``.bashrc'' file in order create
  new commands for the bash shell. This is more flexible than using
  'aliases' because functions may have parameters. Functions may also be
  used within scripts to make those scripts simpler or more readable.

  Functions are simpler than creating a new command with a script placed in
  the path.

\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://www.cyberciti.biz/faq/bash-shell-script-function-examples/}]
     some good information
\end{description}

\emph{ A function to add a function you've defined to .bashrc }
  \begin{lstlisting}
  addfunction () { 
    [ -z "$1" ] && echo "usage: $FUNCNAME <func-name>" && return 1
    declare -f $1 >> ~/.bashrc ;
  }
  \end{lstlisting}

\emph{ Show a usage mesage for the function if no parameters are given }
  \begin{lstlisting}
  function test { 
   if [ -z "$1" ]; then
     echo "usage: $FUNCNAME <parameter>"
     echo " - performs a useful task"
   return 1;
   fi
   ... 
  }
  ,,,,

  * make a function called 'boo' using your last command
  >> boo () { !!; }

  * a function which prints its own name
  >> test () { echo "$FUNCNAME"; }
  
  * a function which prints its own name
  >> test () { [ -z "$1" ] && echo "$FUNCNAME: parameter needed" && return 1; }
  
  * show what each user defined function does
  \begin{lstlisting}
   function fn {
    IFS=$'\n';for f in $(declare -F); { declare -f ${f##* }; } | \
        sed -n '/^_/d;/() *$/s///p;/^ *echo "/{s//  /;s/";//p}' | grep -v 'usage' | less
 }
 \end{lstlisting}
 
 This recipe assumes that user bash functions are documented with 'echo ``blah'''
 statements. The recipe above uses several tricks. Such as sed '/n/s///' which
 reused the matched pattern in a sed expresions. In other words
\begin{lstlisting}
  sed '/x/s///';  
\end{lstlisting}
   is the same as 
\begin{lstlisting}
  sed '/x/s/x//';
\end{lstlisting}
 Functions starting with '\_' are usually defined by the programs, not 
 the user.

\subsection{Traps And Gotchas}

\emph{ Dont use 'exit' to return from a function, use 'return' instead. }
\emph{ Dont use '\$0' for the function name use '\$FUNCNAME' instead  }

  If an alias is reused as a function name, you may get strange 
  incomprehensible errors.

\subsection{Function Definition}

\emph{ Show the definition for the bash function 'af' }
\begin{lstlisting}
  declare -f af
\end{lstlisting}

\emph{ Show help for the bash built-in command 'declare' }
\begin{lstlisting}
  help declare | less
\end{lstlisting}

\emph{ Show all defined functions which dont begin with a '\_' }
\begin{lstlisting}
  declare -F | grep -v " -f _" | less
\end{lstlisting}

\emph{ Define a function with a parameter }
\begin{lstlisting}
  function s { echo $1; }
\end{lstlisting}
\begin{lstlisting}
  s(){ echo $1; }           ~(this is the same)
\end{lstlisting}

\emph{ A function may span 2 or more lines  }
  \begin{lstlisting}
   function x {
     echo 'hello'; }
  \end{lstlisting}

\emph{ A function with one parameter }
  \begin{lstlisting}
    function say {
      echo $1
    }
    say hello  ##(this just prints 'hello' )
  \end{lstlisting}

\emph{ Create a read-onlyfunction }
\begin{lstlisting}
  test(){ echo "Foo"; }; readonly -f test
\end{lstlisting}

\emph{ A recursive function (dont run this, because it is infinite) }
\begin{lstlisting}
  foo(){ foo; }
\end{lstlisting}

\subsection{Example Functions}

\emph{ A function to change into a folder and list its contents  }
\begin{lstlisting}
  function cdls { cd $1; ls; }
\end{lstlisting}

\emph{ Redefine the cd command's behavior using 'builtin' }
\begin{lstlisting}
  cd() { builtin cd "${@:-$HOME}" && ls; }
\end{lstlisting}

\emph{ A function which prints a message and returns if no parameter }
  \begin{lstlisting}
  test () { 
    [ -z "$1" ] && echo "usage: $0 file" && return 1
    cat $1
  }
  \end{lstlisting}

\emph{ A function which calculates the arguments (eg: mm 5*7) }
\begin{lstlisting}
  mm () { echo "$*" | bc -l; }
\end{lstlisting}

\emph{ A function to concatenate input  }
\begin{lstlisting}
  calc(){ awk "BEGIN{ print $* }" ;}
\end{lstlisting}

\emph{ Change directory up a number of levels }
\begin{lstlisting}
  function ..(){ for ((j=${1:-1},i=0;i<j;i++));do builtin cd ..;done;}
\end{lstlisting}

\emph{ Make a folder if it doesnt exist and change into it  }
\begin{lstlisting}
  function mcd() { [ -n "$1" ] && mkdir -p "$@" && cd "$1"; }
\end{lstlisting}

\emph{ Make a function to search the software repositories    }
\begin{lstlisting}
  function af { apt-cache search $@ | less; }
\end{lstlisting}

\emph{ Search for the file and open in vi editor. }
\begin{lstlisting}
  vifind() { vi `find . -name "$1"` }
\end{lstlisting}

\emph{ Function to output an ascii character given its decimal equivalent }
\begin{lstlisting}
  chr () { printf \\$(($1/64*100+$1%64/8*10+$1%8)); }
\end{lstlisting}

\subsection{Function Variables}

\emph{ Make function variables local }
\begin{lstlisting}
  add (){ local x=$1; local y=$2; echo $(( $x + $y )); }
\end{lstlisting}

\section{Doing Nothing At All}

  Despite appearances, doing nothing can be quite useful in fact even
  vital in certain circumstances. 

\emph{ Do nothing for 5 seconds  }
\begin{lstlisting}
  sleep 5
\end{lstlisting}
\begin{lstlisting}
  sleep 5s   ~(the same)
\end{lstlisting}
\begin{lstlisting}
  sleep 2 3  ~(the same)
\end{lstlisting}
\begin{lstlisting}
  sleep 1 4  ~(the same again)
\end{lstlisting}

\emph{ Do nothing for half a second  }
\begin{lstlisting}
  sleep 0.5  ~(gnu sleep)
\end{lstlisting}

\emph{ Do nothing for one hundredth of a second }
\begin{lstlisting}
  sleep 0.01
\end{lstlisting}

\emph{ Do nothing for 5 minutes }
\begin{lstlisting}
  sleep 5m
\end{lstlisting}

\emph{ Do nothing but be successful }
\begin{lstlisting}
  true 
\end{lstlisting}

\emph{ Print 'y' continuously and successfully   }
\begin{lstlisting}
  yes   ~(this is not really doing nothing, but anyway)
\end{lstlisting}

\section{Environment Variables}

  When the user logs in to a bash shell, certain variables are automatically
  set. 


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ important bash environment variables }} \\
  \hline

  \texttt{ \$HOME } & The users home folder \\ 

  \texttt{ \$PATH } & Where executable programs are located \\ 

  \texttt{ \$PWD } & The current working folder \\ 

  \texttt{ \$USER } & The name of the user logged in \\ 

  \texttt{ \$HOST } & The name of the local computer \\ 

    \hline
    \end{tabular}
    \end{center}
\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://tldp.org/LDP/abs/html/internalvariables.html}]
     a good guide to the bash internal variables
\end{description}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ more advanced bash variables }} \\
  \hline

  \texttt{ \$IFS } & Determines how strings are split \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Show the values of the environment variables }
\begin{lstlisting}
  env 
\end{lstlisting}
\begin{lstlisting}
  printenv
\end{lstlisting}

  It is possible to change the value of an environment variable for only
  the following command and not for any subsequent commands. This
  is done as follows

\emph{ Show what time and date it is in new york }
\begin{lstlisting}
  TZ=America/New_York date
\end{lstlisting}

\section{Configuring The Bash Shell}

  Put configuration for the bash shell in '.bashrc' or '.bashprofile'
  New commands for bash can be created either with aliases, 
  functions or scripts.

\emph{ List bash functions defined in .bash\_profile or .bashrc }
\begin{lstlisting}
  declare -F | sed 's/^declare -f //'
\end{lstlisting}

\emph{ Show the path split into lines }
\begin{lstlisting}
  echo $PATH | tr : \\n
\end{lstlisting}

\emph{ Change default shell for all users (freebsd ??) }
\begin{lstlisting}
  cd /usr/home && for i in *;do chsh -s bash $i;done
\end{lstlisting}

\emph{ Enable change directory using variable names }
\begin{lstlisting}
  shopt -s cdable_vars
\end{lstlisting}

\subsection{The Prompt}

\emph{ Display screen window number in the bash prompt }
\begin{lstlisting}
  [[ "$WINDOW" ]] && PS1="\u@\h:\w[$WINDOW]\$ "
\end{lstlisting}
 
\emph{ Display a prompt with colours }
\begin{lstlisting}
  export PS1='\[\033[0;35m\]\h\[\033[0;33m\] \w\[\033[00m\]: '
\end{lstlisting}

\subsection{Aliases}

  Aliases are useful for abbreviating common commands . To save an alias
  put it in the $\sim$/.bashrc file so that it will always be available. The
  limitation of aliases are that they cannot use command line parameters.
  To overcome this use 'functions' instead.

\emph{ Make all searches withing the 'less' pager case-insensitive }
\begin{lstlisting}
  alias less='less -i'
\end{lstlisting}
 
\emph{ Make an alias: a new command 'dir' which calls the ``ls'' command }
\begin{lstlisting}
  alias dir='ls -la | less'  ~(aliases cant use parameters, such as $1)
\end{lstlisting}
  
\emph{ Up - aliaes for moving up the directory tree }
\begin{lstlisting}
  alias up="cd .."; alias upp="cd ../.."; alias uppp="cd ../../.."; 
\end{lstlisting}

\emph{ Make some convenient aliases to edit and reload .bashrc and aliases }
\begin{lstlisting}
  alias aliases='vim ~/.bash_aliases; source ~/.bash_aliases'
\end{lstlisting}
\begin{lstlisting}
  alias bashrc='vim ~/.bashrc; source ~/.bashrc'
\end{lstlisting}

\emph{ Define an alias with a correct automatic completion }
\begin{lstlisting}
  old='apt-get'; new="su-${old}"; command="sudo ${old}"; alias "${new}=${command}"; $( complete | sed -n "s/${old}$/${new}/p" ); alias ${new}; complete -p ${new}
\end{lstlisting}

\emph{ Escape any command aliases }
\begin{lstlisting}
  alias v='less'; \v   ~(the alias is not executed) 
\end{lstlisting}

\section{Miscellaneous}

\emph{ Pretty print a java code 'Co.java' 2 columns, landscape, gaudy header }
\begin{lstlisting}
  enscript -G2rE -b"Assignment 2" -p new.ps Co.java
\end{lstlisting}

\emph{ Switch virtual consoles }
\begin{lstlisting}
  alt+Fn, eg: alt+F1 to go to the first virtual terminal
\end{lstlisting}
  
\emph{ Add a folder to the executable path (put in $\sim$/.bash\_profile file to save it) }
\begin{lstlisting}
  export PATH=/path/to/folder:"${PATH}"
\end{lstlisting}
  (programs in this folder can then be executed with 'programname')

\section{The Command Line}


\section{Command Line History}
 
\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{http://www.deer-run.com/~hal/UnixCommandLineKungFu.pdf}]
  good tips for the command line
\end{description}

  In Unix and Linux commands previously executed at the console
  are stored in a command history and are accessible and 
  manipulable in a variety of ways.
  
\emph{ Copy history from one terminal to another }
\begin{lstlisting}
  history -w <switch to another terminal> history -r
\end{lstlisting}

\subsection{Getting Help For The History}

\emph{ View documentation about the history file }
\begin{lstlisting}
  man bash  ~(then type '/history' to search the documentation)
\end{lstlisting}

\emph{ View the bash help for the 'history' command }
\begin{lstlisting}
  help history
\end{lstlisting}

\subsection{Viewing The Command History}

\emph{ View the command line history }
\begin{lstlisting}
  history  ~(this show the current sessions command history)
\end{lstlisting}

\emph{ View the last 10 commands of the command history }
\begin{lstlisting}
  history 10 
\end{lstlisting}
\begin{lstlisting}
  fc -nl -10  ~(?) 
\end{lstlisting}
\begin{lstlisting}
  history | tail -10   ~(the same)
\end{lstlisting}

\emph{ View recent commands without numbers }
\begin{lstlisting}
  fc -nl
\end{lstlisting}

\emph{ List the last 100 commands in reverse order with no numbers }
\begin{lstlisting}
  fc -rnl -100
\end{lstlisting}

\subsection{Searching The Command History}

\emph{ Search the command history }
\begin{lstlisting}
  [control] + r
\end{lstlisting}
\begin{lstlisting}
  /   ~(the same if the command line is in 'vi' mode)
\end{lstlisting}

\emph{ Insert a comment on command line as a searchable reminder }
\begin{lstlisting}
  ls -alh #mycomment
\end{lstlisting}

\emph{ Display the top 10 commands from the command history }
\begin{lstlisting}
  history | awk '{print $2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -n | tail | sort -nr
\end{lstlisting}

\subsection{Executing From The History}

\emph{ Execute the 47th command in the command history }
\begin{lstlisting}
  !47
\end{lstlisting}

\emph{ Substitute 'l' with 's' in the last command and execute it. }
\begin{lstlisting}
  ^l^s
\end{lstlisting}

\emph{ Remove 'ls' from the last command }
\begin{lstlisting}
  ^ls
\end{lstlisting}

\emph{ Build up command pipelines with !! }
\begin{lstlisting}
  indent | !!     ~(the previous command replaces '!!')
\end{lstlisting}

\emph{ Apply a 'less' pager command to a long text file path }
\begin{lstlisting}
  cat /long/path/name/document.txt
\end{lstlisting}
\begin{lstlisting}
  !! | less       
\end{lstlisting}

\emph{ Run the previous command with root privileges }
\begin{lstlisting}
  vim /etc/vim/vimrc
\end{lstlisting}
\begin{lstlisting}
  sudo !!     ~(this executes 'sudo vim /etc/vim/vimrc')
\end{lstlisting}

\emph{ Use !\$ to get the argument from the last command }
\begin{lstlisting}
  cat file.txt
\end{lstlisting}
\begin{lstlisting}
  vi !$           ~(executes 'vi file.txt')
\end{lstlisting}

\emph{ !\$ - The last argument to the previous command }
\begin{lstlisting}
  svn status app/models/foo.rb; svn commit -m "Changed file" !$
\end{lstlisting}

\emph{ Get the command argument from the second last command }
\begin{lstlisting}
  vi !-2$
\end{lstlisting}

\emph{ Get all arguments from the previous command }
\begin{lstlisting}
  cat a.txt b.txt c.txt
\end{lstlisting}
\begin{lstlisting}
  vi !*        ~(executes 'vi a.txt b.txt c.txt')
\end{lstlisting}

\emph{ Print the last command which begins with the letter 'h' }
\begin{lstlisting}
  !h:p       ~(':p' stops the command from being executed)
\end{lstlisting}

\emph{ Print the last command which contains the string  'hi' }
\begin{lstlisting}
  !?hi?:p     
\end{lstlisting}

\emph{ Print the 507th command with any filename extension removed }
\begin{lstlisting}
  !507:r:p
\end{lstlisting}

\emph{ Print the 512nd command with a 'c' replaced by 'C' }
\begin{lstlisting}
  !512:s/c/C/:p
\end{lstlisting}
\begin{lstlisting}
  !512:s/c/C/    ~(actually execute the command)
\end{lstlisting}
\begin{lstlisting}
  !512:s/c/C     ~(the same)
\end{lstlisting}
\begin{lstlisting}
  !512:s,c,C     ~(the same)
\end{lstlisting}
\begin{lstlisting}
  !512:gs/c/C/   ~(replace all occurrences of 'c' with 'C')
\end{lstlisting}

\emph{ Edit the last 7 commands in a text editor (determined by \$FCEDIT) }
\begin{lstlisting}
  fc -6 0    ~(watch out, the commands are executed after editing!)
\end{lstlisting}
  
\emph{ After fc, to not execute the commands, clear the editor buffer  }
\begin{lstlisting}
  :bd    ~(in vim, assuming that $FCEDIT is set to 'vim' or 'vi')
\end{lstlisting}

\emph{ Runs previous bash command replacing 'tree' with 'leaf' }
\begin{lstlisting}
  ^tree^leaf
\end{lstlisting}

\emph{ Do a command but skip recording it in the bash command history }
\begin{lstlisting}
  _cd ~/nsfw; mplayer midget_donkey.mpeg
\end{lstlisting}

\subsection{Configuring The Command History}

\emph{ Make sure that new commands are appended to the history file }
\begin{lstlisting}
  shopt -s histappend
\end{lstlisting}

\emph{ See in which file your command history is stored }
\begin{lstlisting}
  echo $HISTFILE  ~(this normally show '~/.bash_history')
\end{lstlisting}

\emph{ View your (or the current users) history file }
\begin{lstlisting}
  less ~/.bash_history
\end{lstlisting}
\begin{lstlisting}
  less $HISTFILE    ~(technically better)
\end{lstlisting}

\emph{ See how many commands will be saved to your history file }
\begin{lstlisting}
  echo $HISTSIZE
\end{lstlisting}
 
\emph{ View the maximum number of commands saveable to your history file }
\begin{lstlisting}
  echo $HISTFILESIZE
\end{lstlisting}

\emph{ See how many commands are currently in your history file  }
\begin{lstlisting}
  wc -l $HISTFILE
\end{lstlisting}

\emph{ Get rid of duplicate entries in the command history file }
\begin{lstlisting}
  sort -u $HISTFILE -o $HISTFILE
\end{lstlisting}

\emph{ Make the history file 500000 lines and write 100000 commands each time }
\begin{lstlisting}
  export HISTFILESIZE=500000
\end{lstlisting}
\begin{lstlisting}
  export HISTSIZE=100000
\end{lstlisting}

  put these values in '$\sim$/.bashrc' so they will be permanent

\emph{ Include timestamps for each command in the history file }
\begin{lstlisting}
  HISTTIMEFORMAT=yes
\end{lstlisting}

\emph{ Erase duplicates for the history file }
\begin{lstlisting}
  export HISTCONTROL="erasedups:ignoreboth"
\end{lstlisting}

\emph{ Dont put the 'exit' command in the history file }
\begin{lstlisting}
  export HISTIGNORE="&:[ ]*:exit"
\end{lstlisting}

\subsection{Deleting The Command History}

\emph{ Clear the command history for the current session }
\begin{lstlisting}
  history -c
\end{lstlisting}

\emph{ Delete the command history item 100 }
\begin{lstlisting}
  history -d 100
\end{lstlisting}

\section{Vim And Bash}

  It is possible to execute bash commands from within the vim text editor
  using a variety of techniques. It is also possible to 'filter' parts of a
  document using bash commands or send (pipe) part or all of a text
  document from vim to a bash command.

\emph{ Execute the bash 'date' command from within vim }
\begin{lstlisting}
  :!date
\end{lstlisting}

\emph{ Execute the current line as a bash command (doesnt insert results) }
\begin{lstlisting}
  :.w !bash
\end{lstlisting}

\emph{ Remove the comment character and execute current line as a bash command }
\begin{lstlisting}
  :.w !sed 's/^\#//' | bash
\end{lstlisting}

\emph{ A command to execute a fragment between '---' and ',,,' with bash }
\begin{lstlisting}
  command! Bmr ?^ *---?+1,/^ *,,,/-1w !sed 's/^ *\#//' | bash | less
\end{lstlisting}

  But the command above exits immediately even if the bash commands 
  should read input from the user.

\emph{ A vim command 'Bashr' to execute the current line in bash }
\begin{lstlisting}
  command! Bashr .w !sed 's/^ *\#//' | bash | less
\end{lstlisting}

\emph{ A vim mapping to execute a bash command line in a document  }
\begin{lstlisting}
  map ,bm :.w !sed 's/^ *\#//' \| bash
\end{lstlisting}

\emph{ A vim command to make and show a screen shot of a bash command  }
\begin{lstlisting}
  command! Bci .w !sed 's/^ *\#//' | bash; scrot -ud1 test.png; feh test.png
\end{lstlisting}

  If we are editing a vim document which has a bash command such as "tree |
  head -20" on a line by itself, then we can execute and create a
  screenshot of the executed command using the vim command which we have
  just made above. We can do this by executing the command ``:Bci'' within
  vim
  
\emph{ A vim command to make and show a screen shot saving to a given file name ?? }
\begin{lstlisting}
  command! -nargs=1 Bci .w !sed 's/^ *\#//' | bash; scrot -o<args> -ud1 test.png; feh test.png
\end{lstlisting}

\emph{ Take a delayed screen-shot of the command on the current line  }
\begin{lstlisting}
  :.w !sed 's/^/scrot -ubd1 test.png \& clear; /' | bash; sleep 1.5; feh test.png
\end{lstlisting}

  If the line which the cursor is on in the current document contains
  the text 'top', then executing the above line will run that 
  command in a bash shell and take a screen-shot of its output. The
  screen-shot will then be displayed

\emph{ A command 'Scr' to take a delayed screen-shot and display it }
\begin{lstlisting}
  command! Scr .w !sed 's/^ *\#?/scrot -ubd2 test.png \& clear; /' | bash; sleep 2.5; feh test.png
\end{lstlisting}
   
  If the cursor is positioned on a line with 'apropos sound | less' then
  we can take a screen-shot of the output of that command with ':Scr'

  See the vim 'system' function for more advanced solutions

\emph{ View the help for the vim built function 'system()' }
\begin{lstlisting}
  :h system
\end{lstlisting}

\emph{ Assign to the variable 'a' the output of the bash command 'ls' }
\begin{lstlisting}
  :let a=system("ls")
\end{lstlisting}

\section{Screen Shots Of Bash}

   Sometime it is nice to make a picture of a bash terminal
   in order to try to impress somebody or for other reasons

\emph{ Create a screen shot of the 'top' command }
\begin{lstlisting}
  scrot -ud1 test.png & clear; top  
\end{lstlisting}

\emph{ Make and display a screen shot of a zenity list box in 'sh.png' }
\begin{lstlisting}
  scrot -ubd2 sh.png & ls | zenity --list --column="test"; feh sh.png
\end{lstlisting}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ scrot options }} \\
  \hline

   \texttt{ -u } & Take a screen shot of the focussed window \\ 

   \texttt{ -d2 } & Delay for 2 seconds before capturing the image \\ 

   \texttt{ -b } & When capturing a window, get the window frame as well \\ 

    \hline
    \end{tabular}
    \end{center}
\section{Editing The Command Line}
  
\emph{ Enable programmable bash completion in debian linux }
\begin{lstlisting}
  aptitude install bash-completion ; source /etc/bash_completion
\end{lstlisting}

\emph{ Display all commandline editing keystrokes that use [ctrl] }
\begin{lstlisting}
  bind -p | grep -F "\C"
\end{lstlisting}

\emph{ Show what 'short-cut' keys are available on the command line }
\begin{lstlisting}
  bind -P
\end{lstlisting}

\emph{ Go to end of current command line  }
\begin{lstlisting}
  <control e>
\end{lstlisting}

\emph{ Go to begin of current command line }
\begin{lstlisting}
  CTRL + a
\end{lstlisting}

\emph{ Set the command line editing mode to 'vi'   }
\begin{lstlisting}
  set -o vi      ~(the command line now seems like the 'vi' text editor)
\end{lstlisting}
  
\emph{ Set the command line editing mode to 'emacs' }
\begin{lstlisting}
  set -o emacs   ~(this is the default mode)
\end{lstlisting}
 
\emph{ View the shell edit mode variables }
\begin{lstlisting}
  set -o
\end{lstlisting}

\emph{ Once in 'vi' edit mode, to edit the command line in \$EDITOR text editor  }
\begin{lstlisting}
  [esc] + v    ~(if $EDITOR is 'vim' then vim will open)
\end{lstlisting}

\emph{ Enable vi mode line reading in a shell script and store line in 'a' }
\begin{lstlisting}
  set -o vi; read -e a;   ~(the -e switch uses the 'readline' function)
\end{lstlisting}

\emph{ Change the default text editor for the system  }
\begin{lstlisting}
  export EDITOR=vim    ~(put in .bash_profile)
\end{lstlisting}

\emph{ Make the vi editing mode the default }
\begin{lstlisting}
  set editing-mode vi    ~(put this in the '.inputrc' file)
\end{lstlisting}
  (type 'man readline' for more information)

  Bash command line editing is determined by the 'readline' program 
  Other programs, like 'gnu-plot' also use the same client. 
  Put 'set editing-mode vi' in .inputrc to automatically use
  the 'vi' editing mode for all readline clients./

\section{Encantations}

\emph{ Insert the file name of each html file at the top of the file with no extension }
\begin{lstlisting}
  for f in *.html; do i=${f/.html/}; sed -i.bak "1s/^/$f/" $f; done
\end{lstlisting}

\section{Perl Versus Bash}

  Perl may be much faster than bash if bash is doing looping constructs,
  otherwise not.

\emph{ Loop through input with perl }
  \begin{lstlisting}
  my $state = 0;
  while(<>) {
    exit if /TIMESTAMP2/;
    print $_ if $state == 1;
    $state = 1 if /TIMESTAMP1/;
  }
  \end{lstlisting}

\subsection{Fu Bash Tips}

\emph{ Emulate perl 'print ``\#'' x 20, ``\textbackslash n''' }
\begin{lstlisting}
  printf '%*s\n' 20 | tr ' ' '#'
\end{lstlisting}

\emph{ Getting the last argument from the previous command }
\begin{lstlisting}
  cd !$
\end{lstlisting}

\emph{ Diff on two variables }
\begin{lstlisting}
  diff <(echo "$a") <(echo "$b")
\end{lstlisting}

\emph{ Get the last string of previous command with !\$ }
\begin{lstlisting}
  $mkdir mydir -> mv !$ yourdir -> $cd !$
\end{lstlisting}

\emph{ Perform a branching conditional }
\begin{lstlisting}
  true && { echo success;} || { echo failed; }
\end{lstlisting}

\emph{ Runs previous command replacing foo by bar every time that foo occurs }
\begin{lstlisting}
  !!:gs/foo/bar
\end{lstlisting}

\emph{ Check command history, but avoid running it }
\begin{lstlisting}
  !whatever:p
\end{lstlisting}

\emph{ Clear mistyped passwords from password prompt }
\begin{lstlisting}
  ^u
\end{lstlisting}

\emph{ Invoke an editor to write a long, complex, or tricky command line }
\begin{lstlisting}
  control-x e
\end{lstlisting}

\emph{ Salvage a borked terminal }
\begin{lstlisting}
  reset
\end{lstlisting}

\section{Logging Out}

\emph{ Execute a command on logout }
\begin{lstlisting}
  trap cmd 0
\end{lstlisting}

\emph{ Close shell keeping all subprocesses running }
\begin{lstlisting}
  disown -a && exit
\end{lstlisting}

\section{Colours}
  
\emph{ Make folder listings always colourized }
\begin{lstlisting}
  alias ls='ls --color=always'
\end{lstlisting}

  Colours on the screen can be obtained using Ansi escape sequences 
  and the 'echo' command

\emph{ Display a red 'R' and a yellow 'Y' on the screen }
\begin{lstlisting}
  echo -e "\033[1;31mR\033[1;33mY"
\end{lstlisting}

\emph{ Display hi in all the colours  }
\begin{lstlisting}
  echo -e "\x1B["{0..1}";3"{0..7}"m hi"
\end{lstlisting}

  The line above uses bash exterpolation to generate a 
  set of strings.

\emph{ Display hello in red (uses a hex code and no bold) }
\begin{lstlisting}
  RED="\x1B[31m"; echo -e "$RED hello"
\end{lstlisting}

\emph{ Show redish text }
\begin{lstlisting}
  echo -e "\033[47m\033[1;31m  Light Red on a grey background"
\end{lstlisting}
\begin{lstlisting}
  echo -e "\033[1;31m  Light Red "
\end{lstlisting}

\emph{ Remove color codes (special characters) with sed }
\begin{lstlisting}
  sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
\end{lstlisting}

\emph{ Make a set of colour variables to use with 'echo -e'  }
  \begin{lstlisting}
    BLACK="\x1B[0;30m";
    GREY="\x1B[1;30m";
    RED="\x1B[0;31m";
    BRED="\x1B[1;31m"
    GREEN="\x1B[0;32m"
    BGREEN="\x1B[1;32m"
    YELLOW="\x1B[0;33m"
    BYELLOW="\x1B[1;33m"
    BLUE="\x1B[0;34m"
    BBLUE="\x1B[1;34m"
    MAGENTA="\x1B[0;35m"
    BMAGENTA="\x1B[1;35m"
    CYAN="\x1B[0;36m"
    BCYAN="\x1B[1;36m"
    WHITE="\x1B[0;37m"
    BWHITE="\x1B[1;37m"
    NORMAL="\x1B[0m"
  \end{lstlisting}

\emph{ Display some colours }
  \begin{lstlisting}
  echo -e "
     $BLACK BLACK $NORMAL x1B[0;30m 
     $GREY GREY $NORMAL x1B[1;30m 
     $RED RED $NORMAL x1B[0;31m 
     $BRED BOLD RED $NORMAL x1B[1;31m 
     $GREEN GREEN $NORMAL x1B[0;32m
     $BGREEN BOLD GREEN $NORMAL x1B[1;32m
     YELLOW=x1B[0;33m
     BYELLOW=x1B[1;33m
     BLUE=x1B[0;34m
     BBLUE=x1B[1;34m
     MAGENTA=x1B[0;35m
     BMAGENTA=x1B[1;35m
     CYAN=x1B[0;36m
     BCYAN=x1B[1;36m
     WHITE=x1B[0;37m
     BWHITE=x1B[1;37m
     NORMAL=x1B[0m
  "
  \end{lstlisting}



  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ a list of colour escape codes }} \\
  \hline

  \texttt{ Black } & 0;30  \\ 

  \texttt{ Dark Gray } & 1;30 \\ 

  \texttt{ Red } & 0;31 \\ 

  \texttt{ Bold Red } & 1;31 \\ 

  \texttt{ Green } & 0;32 \\ 

  \texttt{ Bold Green } & 1;32 \\ 

  \texttt{ Yellow } & 0;33  \\ 

  \texttt{ Bold Yellow } & 1;33  \\ 

  \texttt{ Blue } & 0;34  \\ 

  \texttt{ Bold Blue } & 1;34  \\ 

  \texttt{ Purple } & 0;35  \\ 

  \texttt{ Bold Purple } & 1;35  \\ 

  \texttt{ Cyan } & 0;36  \\ 

  \texttt{ Bold Cyan } & 1;36 \\ 

  \texttt{ Light Gray } & 0;37 \\ 

  \texttt{ White } & 1;37 \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Colored prompt }
\begin{lstlisting}
  export PS1='\[\033[0;35m\]\h\[\033[0;33m\] \w\[\033[00m\]: '
\end{lstlisting}

\section{Unicode Characters}

\emph{ Print some unicode characters }
\begin{lstlisting}
  /usr/bin/printf '\u201cdouble\u201D'
\end{lstlisting}

  The '/usr/bin/printf' is necessary because otherwise the bash 
  built-in printf command is used which doesnt print unicode

\emph{ Install the enjoyable 'unicode' command line program on a debian box }
\begin{lstlisting}
  sudo apt-get install unicode
\end{lstlisting}

\emph{ Show all unicode characters relating to chess }
\begin{lstlisting}
  unicode chess
\end{lstlisting}

\section{Ansi Escape Sequences}
  
\emph{ Save the current cursor position }
\begin{lstlisting}
  echo -n -e "\033[s"
\end{lstlisting}

\emph{ Restore the cursor to its former position }
\begin{lstlisting}
  echo -n -e "\033[u"
\end{lstlisting}

\emph{ Doesnt seem to work }
  \begin{lstlisting}
    # 2 is green  
    COLOR=`tput setaf 2; tput smso`
    # back to normal screen colors
    NORMAL=`tput sgr0`
    # print the time-date output on the above position
    echo -n $COLOR$cmd$NORMAL
  \end{lstlisting}

\section{Knowledgable Bash People}

  ``foonly'', sydney: http://forums.whirlpool.net.au/user/44690
  hoyhoy at stackoverflow.com
  terson at stackoverflow.com
  amarillion at stackoverflow.com

\section{Terminals}

  The term 'terminal' is very ambiguous. I cant supply a good definition at
  this stage. But it has to do with similar concepts of the console,
  command-line, shell etc. 


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ terminal jargon }} \\
  \hline
\begin{description}[labelindent=1cm, leftmargin=2cm, style=nextline]
 \item[\url{line}] wrapping
     When the text of a line is too long for the computers screen then
     the line may be broken or 'wrapped' so that the extra text is 
     displayed on the next line in the computer screen. This is called
     'line wrapping' or just 'wrapping' 
  @@ 
\end{description}

\emph{ Clear the screen }
\begin{lstlisting}
  clear
\end{lstlisting}

    \hline
    \end{tabular}
    \end{center}
\emph{ Change the window title of the xterm terminal to 'KungFu' }
\begin{lstlisting}
  echo "^[]0;KungFu^G"
\end{lstlisting}

\emph{ Make the text on the screen 'bold' (brighter and thicker than normal) }
\begin{lstlisting}
  tput bold
\end{lstlisting}

\emph{ Use tput to save, clear and restore the terminal contents }
\begin{lstlisting}
  tput smcup; echo "Doing some things..."; sleep 2; tput rmcup
\end{lstlisting}

  The tput command has many options and switches

\emph{ Determine number of lines in terminal }
\begin{lstlisting}
  l=100; while [ $l -gt 1 ]; do echo $l; l=$(($l-1)); done
\end{lstlisting}

\emph{ Change the terminal title to the last shell command executed }
\begin{lstlisting}
  trap 'echo -e "\e]0;$BASH_COMMAND\007"' DEBUG
\end{lstlisting}

\emph{ Start a gnome terminal with three open tabs }
\begin{lstlisting}
  gnome-terminal --tab --tab --tab
\end{lstlisting}
 
\emph{ Print the output of a script on a different terminal  }
\begin{lstlisting}
  script -f /dev/pts/3
\end{lstlisting}
\begin{lstlisting}
  script /dev/null | tee /dev/pts/3   ~(another way to do it)
\end{lstlisting}

\emph{ Stop text lines from wrapping in your terminal }
\begin{lstlisting}
  function nowrap { export COLS=`tput cols` ; cut -c-$COLS ; unset COLS ; }
\end{lstlisting}

\emph{ Using the urxvt terminal daemon }
\begin{lstlisting}
  urxvtd -q -o -f
\end{lstlisting}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ terminal tools }} \\
  \hline

  \texttt{ terminfo } & A database about the terminal screen \\ 

  \texttt{ tput } & A utility for the terminal \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Change title of terminal window to verbose info useful at login }
\begin{lstlisting}
  echo -ne "\033]0;`id -un`:`id -gn`@`hostname||uname -n|sed 1q` `who -m|sed -e "s%^.* \(pts/[0-9]*\).*(\(.*\))%[\1] (\2)%g"` [`uptime|sed -e "s/.*: \([^,]*\).*/\1/" -e "s/ //g"` / `ps aux|wc -l`]\007"
\end{lstlisting}
  
\emph{ Changing the terminal title to the last shell command }
\begin{lstlisting}
  [[ "x$TERM" == "xrxvt" || "x$XTERM_VERSION" == xXTerm* || "x$COLORTERM" == 'gnome-terminal' && "x$SHELL" == */bin/zsh ]] && preexec () { print -Pn "\e]0;$1\a" }
\end{lstlisting}

\subsection{Resetting The Terminal}

\emph{ Salvage a borked terminal }
\begin{lstlisting}
  echo <ctrl-v><esc>c<enter>
\end{lstlisting}

\emph{ Salvage a borked terminal }
\begin{lstlisting}
  <ctrl+j>stty sane<ctrl+j>
\end{lstlisting}

\section{Busybox}

  Busybox is a minimal set of commands including a version of the bash
  shell designed to be used on 'small' computers (having limited resources,
  such as memory, disk storage etc)

\section{Curiosities}

\emph{ Implement a daemon using bash  }
\begin{lstlisting}
  echo "Starting Daemon"; ( while :; do sleep 15; echo "I am still running =]"; done ) & disown -h -ar $!
\end{lstlisting}

  A 'daemon' is a program which runs in the background waiting to
  provide some service or respond to some situation.

\emph{ Search back through previous commands }
\begin{lstlisting}
  Ctrl-R <search-text>
\end{lstlisting}

\emph{ Turn on/off keyboard leds via commandline }
\begin{lstlisting}
  xset led 3
\end{lstlisting}

\emph{ Let your computer lull you to sleep }
\begin{lstlisting}
  echo {1..199}" sheep," | espeak -v english -s 80
\end{lstlisting}

\emph{ Change newlines to space in a file by using echo }
\begin{lstlisting}
  echo $(</tmp/foo)
\end{lstlisting}

\emph{ Convert mouse movements into a type of noise (not on BSD) }
  \begin{lstlisting}
   while true; do 
     beep -l66 -f`head -c2 /dev/input/mice|hexdump -d|awk 'NR==1{print $2%10000}'`;
   done
  \end{lstlisting}

\emph{ A smiley face bash prompt }
\begin{lstlisting}
  PS1="\`if [ \$? = 0 ]; then echo \e[33\;40m\\\^\\\_\\\^\e[0m; else echo \e[36\;40m\\\-\e[0m\\\_\e[36\;40m\\\-\e[0m; fi\` \u \w:\h)"
\end{lstlisting}

BASH 4.0 TOPICS 

  Bash 4.0 is said to be introducing recursive globbing
  with the '**' operator.

\emph{ Change to the home (\$HOME) folder in zsh or the bash v4 shell }
\begin{lstlisting}
  ~
\end{lstlisting}
 
\emph{ Arithmetic series with a 'step' value in bash version 4 }
\begin{lstlisting}
  echo {1..8..2}
\end{lstlisting}

\section{Things To Investigate}

\emph{ Teminator }
\emph{ Xclip }
\emph{ The cli apps site }
\emph{ Launchy for lauching scripts }
\emph{ Sam2p image processing }
\emph{ SIR simple image resizer }
  webpack for reducing websites
  pngout
  /etc/ppp/ip-up for dns
  makeself
  httrack
  
\section{Utas}

\emph{ On apple: $<$apple-k$>$ smb://alacritas }

\emph{ Mount a samba share from mac osx at the university of tasmania }
\begin{lstlisting}
  mount -t smbfs //user@alacritas/user  smb
\end{lstlisting}
  
\section{Unix Culture}
 
  Unix embodies a particular type of culture. Here are some of the 
  things it encompasses.


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ unix culture }} \\
  \hline

  \texttt{ use folders for what their designed for } & Put temp stuff in /tmp \\ 

  \texttt{ lots of pipes } \\ 

  \texttt{ short commands } \\ 

    \hline
    \end{tabular}
    \end{center}

   \end{document}
