More About Shell Script: Adding Conditions And GUI

terminal-iconIn our last article, we went over some easy-to-use tricks to make simple but useful shell scripts. Now we’ll dive in a little more and add some intelligence to them.

If you remember the script we wrote last time, it ran a series of commands that used Pandoc to generate four versions of a Markdown document (in each of HTML, DOCX, ODT, and ePub). But this was all or nothing… either we used Pandoc itself to make them one at a time, or else all of them. What if we wanted to pick and choose?

This is simple using Conditionals, which are basically “if X is this, then do this” statements. Let’s take a look at the script as we had it:

#!/bin/bash
pandoc -r markdown -w html -o $1.html $1 &&
pandoc -r markdown -w docx -o $1.docx $1 &&
pandoc -r markdown -w odt -o $1.odt $1 &&
pandoc -r markdown -w epub -o $1.epub $1

Suppose we want to be able to pick one of the above items at the command line, or do all of them. A quick modification to the pandoc-pub.sh script like so will accomplish just that:

#!/bin/bash
file=$1
export=$2
if [ "$export" == "html" ]
then
  pandoc -r markdown -w html -o $file.html $file
elif [ "$export" == "docx" ]
then
  pandoc -r markdown -w docx -o $file.docx $file
elif [ "$export" == "odt" ]
then
  pandoc -r markdown -w odt -o $file.odt $file
elif [ "$export" == "epub" ]
then
  pandoc -r markdown -w epub -o $file.epub $file
fi

The first thing we did here is to give the two variables we want from the command line names: file (which is the Markdown source file), and export (which is the format we want to export to. So now we can pick and choose what we want to generate by using:

pandoc-pub.sh [file you want to convert].md [one of either "html," "docx," "odt," or "epub"]

But what about the whole shebang? We could do that last time, but not now? Well, if we think ahead a little, we should account for a case where we (or another user) enters something besides the four choices above – in this case, why not export everything? Add one more bit of code as follows:

#!/bin/bash
file=$1
export=$2
if [ "$export" == "html" ]
then
  pandoc -r markdown -w html -o $file.html $file
elif [ "$export" == "docx" ]
then
  pandoc -r markdown -w docx -o $file.docx $file
elif [ "$export" == "odt" ]
then
  pandoc -r markdown -w odt -o $file.odt $file
elif [ "$export" == "epub" ]
then
  pandoc -r markdown -w epub -o $file.epub $file
else
  pandoc -r markdown -w html -o $file.html $file &&
  pandoc -r markdown -w docx -o $file.docx $file &&
  pandoc -r markdown -w odt -o $file.odt $file &&
  pandoc -r markdown -w epub -o $file.epub $file
fi

Now, if we enter nothing after the filename at the command line (or the wrong thing), this script will just do the safe thing and generate all the formats.

But what if, in this last case, you don’t want it to just generate everything, but do something more helpful. We could add another

elif

statement to generate all formats when “all” is entered at the command line, and change the statement to print some help text:

#!/bin/bash
file=$1
export=$2
if [ "$export" == "html" ]
then
  pandoc -r markdown -w html -o $file.html $file
elif [ "$export" == "docx" ]
then
  pandoc -r markdown -w docx -o $file.docx $file
elif [ "$export" == "odt" ]
then
  pandoc -r markdown -w odt -o $file.odt $file
elif [ "$export" == "epub" ]
then
  pandoc -r markdown -w epub -o $file.epub $file
elif [ "$export" == "all" ]
then
  pandoc -r markdown -w html -o $file.html $file &&
  pandoc -r markdown -w docx -o $file.docx $file &&
  pandoc -r markdown -w odt -o $file.odt $file &&
  pandoc -r markdown -w epub -o $file.epub $file
else
  echo "Please add one of the following options after the filename: html, odt, docx, epub, or all."
fi

But it will be more useful that, in the event of a blank or incorrect flag, we display a GUI to help the user along. First, we’ll need to install a set of tools called Zenity to help us. You can install this from the Software Centre, or use the following command:

sudo apt-get install zenity

Next, we’ll need to use Zenity to create a dialog for us. We’ll want something where the user can select all or some of the options we have available… checkboxes sounds like the right thing here. So we create a Zenity dialog with checkboxes representing all of our options:

#!/bin/bash
zenity --list --checklist --title="Pandoc Publisher" --column="" --column="Export Format" FALSE "html" FALSE "odt" FALSE "docx" FALSE "epub"

zenity-dialog

You can see how the above Zenity command is constructed by reading the manual here. Next, we need to get the list of whatever the user checks, and assign it to a variable. Adding a variable name, and wrapping the Zenity command in parentheses, and adding a “$” sign will tell the shell to replace the command inside with its result when it’s done:

#!/bin/bash
choices=$(zenity --list --checklist --title="Pandoc Publisher" --column="" --column="Export Format" FALSE "html" FALSE "odt" FALSE "docx" FALSE "epub");

Now we have a variable “$choices” that contains a list (separated by “|” by default) of all the options selected. We’ll need to check to see if that list contains any of the formats we’re planning to handle using “=~” instead of “==” (this checks to see if something contains something else, in this case)… for example:

if [[ $choices =~ "html" ]]

Lastly, a quick modification of the script will show this dialog when no format is provided, then run the appropriate Pandoc command when that option is checked in the dialog:

#!/bin/bash
file=$1
export=$2
if [ "$export" == "html" ]
then
  pandoc -r markdown -w html -o $file.html $file
elif [ "$export" == "docx" ]
then
  pandoc -r markdown -w docx -o $file.docx $file
elif [ "$export" == "odt" ]
then
  pandoc -r markdown -w odt -o $file.odt $file
elif [ "$export" == "epub" ]
then
  pandoc -r markdown -w epub -o $file.epub $file
elif [ "$export" == "all" ]
then
  pandoc -r markdown -w html -o $file.html $file &&
  pandoc -r markdown -w docx -o $file.docx $file &&
  pandoc -r markdown -w odt -o $file.odt $file &&
  pandoc -r markdown -w epub -o $file.epub $file
else
  choices=$(zenity --list --checklist --title="Pandoc Publisher" --column="" --column="Export Format" FALSE "html" FALSE "odt" FALSE "docx" FALSE "epub");
  if [[ $choices =~ "html" ]]
  then
    pandoc -r markdown -w html -o $file.html $file;
  fi
  if [[ $choices =~ "odt" ]]
  then
    pandoc -r markdown -w docx -o $file.docx $file;
  fi
  if [[ $choices =~ "docx" ]]
  then
    pandoc -r markdown -w odt -o $file.odt $file;
  fi
  if [[ $choices =~ "epub" ]]
  then
    pandoc -r markdown -w epub -o $file.epub $file;
  fi
fi

Just like that, a personalized application with GUI and command-line options.