Bash 101

Inspiration and Attribution

I’ve written some bash over the years. I’m a big fan of building out robust .bash_profiles, but I’ve always just “hacked” on Bash. I’d try writing some logic three or four[1] times until I found the syntax that “worked.” I’ve read tutorials, documentation, and blog posts on bash, but I’ve never “grokked it.”

Then, at MidwestPHP 2018 I got to attend a talk titled “BASHing at the CLI.” It was given by Chris Tankersley, @dragonmantank on Twitter.

That was a great talk. I learned a lot, and immediately after I sat down at my Mac to work through the things I learned.

What follows is a poor substitute for Tankersley’s talk (and his expertise), but I wanted to get it written down, if only to help me absorb.

Shameless Plug

MidwestPHP is a great conference. If you have any interest in PHP, and live, or want to travel to the “midwest” (or the “North” as I think we’re supposed to call it now…) - you should come!

I’m one of the organizers, and have been for years, so I’m maybe a little bias. But… Still:

Go to MidwestPHP.

Bash

What is Bash?

“Bash is the GNU Project’s shell. Bash is the Bourne Again SHell. Bash is an sh-compatible shell that incorporates useful features from the Korn shell (ksh) and C shell (csh). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers functional improvements over sh for both programming and interactive use. In addition, most sh scripts can be run by Bash without modification.” - GNU

Bash is a low level language that interfaces directly with other Unix utilities. It’s commonly used in ops because most Unix systems can run it without having to install any external dependancies. It’s also commonly used in .bash_profiles to construct utilities like:

#!/usr/bash
rebase () {
  git checkout master   
  git pull origin master  
  git checkout $1  
  git pull --rebase origin master  
  git rebase -i `git merge-base $1 master`  
}

What do I need to know first?

Shebang

A bash script start’s with a shebang, and the path to the bash executable you mean to use:

#!/usr/bash

Bash is Inconsistent

An if statement ends with fi, a case statement ends with esac (“if” and “case” backwards). But a for loop ends with done not rof.

Spaces Matter

foo="bar" is valid Bash. foo = "bar" will not do what you think it will:

#!/usr/bash
foo = "bar"

...

> # terminal
> bash foo.sh
foo.sh: line 2: foo: command not found

Spaces also matter in if statements. if [ 0 -eq 1 ]; then is valid Bash, if [0 -eq 1]; then will not work like you think it will:

#!/usr/bash
if [0 -eq 1]; then
  echo "bar"
fi

...

> bash foo.sh
foo.sh: line 2: [0: command not found

Variables are Global by Default

Variables are global unless explicitly set to be local.

#!/bin/bash
function foo()
{
  BAR="baz"
}
foo
function fizz()
{
  local BUZZ="fizzbuzz"
}
foo

...

> bash foo.sh
baz

# ^ note the empty line above where "fizzbuzz" isn't

Functions Don’t Have Defined Parameters

You don’t get to do function foo(variable_1, variable_2) in Bash. Your function can still take parameters, just not with a method signature.

#!/bin/bash
function foo()
{
  echo "${1}"
}
foo Hello World
foo "Hello World"
...

> # terminal
> bash foo.sh
Hello
Hello World

Comparisons Work Differently for Strings and Integers

String comparison:

if [ "foo" == "bar" ] # Equal to if [ "foo" != "bar" ] # Not equal to

Integer comparison:

if [ 1 -eq 0 ] # Equal to if [ 1 -ne 0 ] # Not equal to if [ 1 -gt 0 ] # Greater than if [ 1 -ge 0 ] # Greater than or equal to if [ 1 -lt 0 ] # Less than if [ 1 -le 0 ] # Less than or equal to

Exiting

All bash scripts should exit with a integer. By convention and expectation 0 is “success” - 200 OK-esque.

exit 0

You may define any other integer to convey other meanings as appropriate, exit 1 is a conventional “error” - 500 Error-esque.

Bash 101

The following script prints “Hello World” using a variety of methods available in Bash.

Bash Formatting

Tankersley mentioned the Google Bash Style Guide. I’ve read through it and tried it out a bit, but I haven’t used it enough to recommend one way or another, but there it is.


  1. Or ten.