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.
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 toconfig/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.