October 20, 2015

Workflow Automation: Bin Scripts

By Drew Barontini

Workflow automation improves efficiency and productivity, and there are a variety of ways to achieve it. Continuing on in the series on workflow automation, let’s turn our attention to bin scripts.

This is the second article in a series on workflow automation. If you want to get caught up to this point, read the first article.

What are bin scripts?

First off, what in the world are “bin scripts”?

A self-contained file with a series of shell commands.

In its simplest form, a bin script is just a series of shell commands that you run to perform a task or operation. Rather than using a function, you can use a bin script to create a complex set of conditional tasks.

Why use a bin script instead of a function?

That’s a great question! I’d use a bin script over a function if:

  • You want to have a self-contained set of commands in a single file
  • You want to have multiple, related functions together
  • You have complex flow logic

How to write one

Let’s talk about how to write a bin script.

Create the file

First, create the file.

touch script-name

We don’t have to use a file extension.

Specify the interpreter

Next, we add the following to the top of the file:

#!/usr/bin/env bash

That way, the shell knows which interpreter to run. After that, we can run any shell commands we’d like. For example:

mkdir files
touch files/file
# ...

Using Ruby

Instead of using Bash, we can also write a bin script in Ruby. To do so, start the file with a different interpreter, like so:

#!/usr/bin/env ruby

And then we can use Ruby commands within the file.

puts 'Hello!'

Pretty cool, right?

Setting permissions

Next, to run the script from the command line, we’ll need to change the file permissions so it’s executable:

chmod +x script-name

Adding to the PATH

PATH is an environment variable on Unix-like operating systems, DOS, OS/2, and Microsoft Windows, specifying a set of directories where executable programs are located.

Wikipedia

The last step is to make sure that the bin script is in your $PATH. If you’re not familiar with the $PATH, just know it’s the place your shell will look for which files, in which order, to execute.

To see what the $PATH looks like, echo it out:

echo $PATH

You will (or should) see a string, separated by colons, that displays the order the computer looks for a given command.

To make sure that the shell finds our new bin script(s), I recommend putting it in dotfiles. Let’s say, for example, our bin scripts are in ~/.dotfiles/bin. If that’s the case, we’ll need to add it to the $PATH variable. In our .bash_profile (or similar):

export PATH="$PATH:$HOME/.dotfiles/bin"

This sets the $PATH variable to the current $PATH, plus the path to our bin/ directory containing our bin scripts. Now our computer knows where to look when we run our script on the command line.

Tip: Run the echo $PATH command to make sure that it worked as expected.

Running

Now, from the command line, simply type the script name and hit enter.

script-name

The script-name is the same name as the file.

That’s all there is to it!

Proper file structure

As a small aside, let’s talk about how we can document and structure a bin script.

The file should be self explanatory.

#!/usr/bin/env bash
# ****************************************************
#
#   Script Name
#   -> The description of the script
#
# ----------------------------------------------------
#   Dependencies
# ----------------------------------------------------
#
#   Add any dependencies the script has...
#
# ----------------------------------------------------
#   Usage
# ----------------------------------------------------
#
#  `script-name` - argument-less version of the script
#  `script-name argument` - script with argument
#
# ****************************************************

# Error handling

set -o errexit
set -o nounset
set -o pipefail

# ----------------------------------------------------
#   Functions
# ----------------------------------------------------

# ...

# ----------------------------------------------------
#   Variables
# ----------------------------------------------------

# ...

# ----------------------------------------------------
#   Main
# ----------------------------------------------------

if (( "$#" == 0 )); then

  # They didn't pass any arguments.
  # If it requires an argument, you can output usage info here.

else

  # They did pass arguments...

fi

Examples

Now, to keep things applicable, I’d like to talk about a few examples of bin scripts.

For brevity’s sake, I’ve left out all the commenting structure mentioned above.

Downloading a set of files

Have you ever wanted to pull down a file, or set of files, from a GitHub project? Sometimes we just need a few files without having to clone the entire project. A bin script is perfect in this situation.

REPOURL='https://raw.githubusercontent.com/drewbarontini/noise/master'

echo 'Downloading...'

curl -s "$REPOURL/gulpfile.js" >> 'gulpfile.js'
curl -s "$REPOURL/package.json" >> 'package.json'

echo 'Successfully set up drewbarontini/noise!'

This bin script will curl two files from the drewbarontini/noise repository and save them locally. It’s simple, but saves several steps of manually downloading the files from GitHub.

Setting up a new project

In order to set up a Rails project, you have to follow a set of steps, such as:

  • Running bundle install
  • Duplicating the config/database.example.yml file to config/database.yml
  • Running rake db:create db:migrate db:seed

We can do this manually, but let’s save some time with a bin script.

echo "Running 'bundle install'..."
bundle install

echo 'Setting up the database...'
cp config/database.example.yml config/database.yml
bundle exec rake db:create db:migrate db:seed

Now, instead of running those commands manually, we just type the script name and hit enter. These small workflow efficiency gains add up when we automate them.

Your setup for a Rails project may vary, so adjust accordingly.

That’s All, Folks

Those are just a few examples of the usefulness of workflow automation with bin scripts. Use them to automate repetitive tasks, shorten longer tasks, and increase your workflow automation to work more efficiently.

© 2019 Drew Barontini — Building products under Drewbio, LLC