In Praise of Small Shell Scripts
Later: Making A Tiny E-Paper Status Display for the Raspberry Pi Zero
Earlier: 2024 Blogging Intentions
Over the decades I've relied heavily on bash
aliases and functions to
automate common tasks, resulting in a .bash_profile
that's over a
thousand lines long. But lately I find myself writing many small
scripts instead.
These tiny scripts, which live in a directory on my
$PATH
, have several advantages:
- They compose nicely, in line with the Unix philosophy.
- They are reasonably portable. If it works for me on Linux, it'll often work on my Mac, and vice versa.
- They start quickly and are often as fast as something you'd write in Python, Ruby, etc.
- Their file creation / modification times are distinct and provide a
history of what you worked on, when; by contrast, everything in
.bash_profile
is muddied together. - They run in subprocesses without needing to get your
.bash_profile
involved (helpful for Org Babel or any situation where you need to run your script from another program).
Even something as trivial as an alias might get its own shell script, if I can give it a name that's easier to remember than the original program name or combination of arguments. Bash is an awkward language for doing complex things, but expressive enough for simple tasks. And ChatGPT or other AI tools can often write simple scripts correctly for you with little or no modification.
Here are some examples of small scripts I've been using recently:
ghjobs
: Show status of my active CI jobs on GitHub (wrapper aroundgh
tool); avoids having to go to the Web site, usable insidewatch
, etc.inprog
/ondeck
: Show GitHub issues tagged as "in progress" or "on deck," across all my "work" repositories;- (several programs) : Run one of many different build variants on the embedded system I'm working on (build for Mac, build for target hardware, build with fast tests, build all variants prior to pushing code, etc.);
- (several programs) : Select random figurative references for inspiration or to draw from (there are many variations of this one);
bashscript
: Create a newbash
script in the appropriate place (on$PATH
).
This last one is simple and helpful enough to show here:
#!/bin/bash
script_name=$1
cat << EOF > ~/bin/$script_name
#!/bin/bash
echo "OK"
EOF
chmod +x ~/bin/$script_name
Bash is boring and old (I still have csh
scripts from more than 30
years ago; csh
is a close cousin of bash
). It's also everywhere
– on my Mac, inside my Docker containers, on my Raspberry Pi's, on my
client's servers, and on the cloud VMs I work on.
The "many small scripts" approach is complementary to how I use
make
, which I wrote about previously.
Finally, here's the small script I wrote yesterday to hopefully get me writing more often:
#!/bin/bash
BLOGHOME=${BLOGHOME:-$HOME/Docs/websites/johnj22}
cd $BLOGHOME
pwd
echo -n "Title for post: "; read title
postdate=$(date '+%Y-%m-%d')
echo $title $postdate
# Turn the title lower case/kebab case, remove extra characters. Thanks, ChatGPT!
title_kebab=$(echo "$title" |
tr '[:upper:]' '[:lower:]' |
tr -s '[:space:]' '-' |
sed 's/[^a-z0-9-]//g; s/^-//; s/-$//')
echo -n "$title" | pbcopy
file="content/posts/$title_kebab"".org"
if [ ! -e $file ]; then
cat <<EOF > $file
---
title: $title
date: $postdate
draft: true
tags:
---
# Org Mode stuff in case I export the document on its own without using Hugo:
#+OPTIONS: toc:nil num:nil
EOF
fi
ae $file # `ae` is another small script: loads the resulting file in Emacs.
Typing "newpost" asks me for a title and pops me in my editor with all the boilerplate needed to get me on my way. Nice and easy.
Later: Making A Tiny E-Paper Status Display for the Raspberry Pi Zero
Earlier: 2024 Blogging Intentions