Bash-Based Decision Support Systems

It is a well known fact that decision making is tiring. One of the more difficult decisions our team face every day is where to go for lunch. To avoid post lunch decision fatigue, we started automating the process.

Here is the first version of the script using the venerable rl utility.

rl -c 1 << HERE | say
Papa Pane

In this case we had to generate the candidates manually. In a lot of decision situations that is acceptable. However there are also situations where the machine can help generating candidates. For our lunch problem we devised the following solution:

curl -s \
      --data-urlencode "cat=eat-drink" \
      --data-urlencode "in=52.5304,13.3864;r=640" \
      --data-urlencode "size=15" \
      --data-urlencode "pretty" \
      --data-urlencode "app_code=NYKC67ShPhQwqaydGIW4yg" \
      --data-urlencode "app_id=demo_qCG24t50dHOwrLQ" \
      --get '' \
      | jsed --raw 'function(r)
             i.title + " (distance " + i.distance.toString() + "m)"
         ).join("\n")' \
      | rl -c 1

This would yield something like this:

Weinbar Rutz (distance 252m)

It uses the Nokia RESTful Places API to find places within 640m around our office. Conveniently its playground environment already creates a curl statement for us. Then we pipe the result through jsed to extract the important information from the JSON response, before we task rl with taking the actual decision for us.


Cleaning up your Working Copy

It is a common step in build scripts to cleanup the local working copy to ensure that no potentially stale artifacts from previous builds are being used and that files that are needed by the build are being checked in.

Git conveniently allows deletion of all ignored files, as well as files that are neither staged nor committed, like this:

#!/usr/bin/env bash
# Removes everything that is not checked in
git clean -f -x -d

This is good enough for a build server, however on your personal working copy you don’t want to inadvertently delete work you haven’t staged yet. So instead a slightly more involved cleanup procedure can be used. It will actually fail the cleanup if there are unstaged files that are not ignored, and list those files. Otherwise it will just delete the ignored files.

#!/usr/bin/env bash
# Removes everything that is not checked in
set -e
untracked=$(git ls-files --other --exclude-standard)
if [ "$untracked" ]; then
    echo "These files are neither tracked nor ignored:"
    echo "$untracked"
    exit 1
fi >&2
git clean -f -x -d