Embracing Shell Scripts
The year: 2022. The place: Southern Wisconsin. The scene: a programmer trying his utmost to find the words to explain his passion for shell scripting and automation. Okay, let me stop there before this article goes way off the deep end of silliness. This isn’t Star Trek, and I’m nowhere near that cool. Yet, I’d like to tell you about something I find very exciting, the world of shell scripting and automation.
Before you click away and go back to coding in your editor with all its amazing GUI tools (don’t worry, I’m not against modern editors, they are awesome), hear me out for just a bit. As a developer, you’ve no doubt used your shell to some degree. Perhaps cloning a git repository, navigating your directory structure, or running the sketchy-looking command you found on StackOverflow that magically fixes the issue your computer was having. However, behind the shell you use lays a whole world of productivity improvements and automation you can tap into.
What’s the point though?
When I first started digging deeper into documentation surrounding shell script
in bash/zsh/fish, I found myself asking the question “what’s the point?” or
“what can I automate that actually helps my daily work?” So, my goal in this
article is going to be to share some of my favorite shell scripts and associated
workflow improvements to help inspire you to consider what you can build. I’m
not going to dive too deep into how every piece works, there are tons of
resources already about learning bash
or your favorite shell scripting
language.
So, let’s dive in!
Printing the most recent commit URL
From time to time, when discussing a PR with coworkers, I’ll commit and push a change to GitHub, and then copy the URL of that commit to send them in Slack or add to a comment thread in the pull request. Previously, I didn’t have a great process to do this, often resulting in opening up my git graph in VS Code and remembering what to click to copy the commit URL, or going into the branch in GitHub to manually find the URL.
To simplify this, I created a commit-url
script which will print the URL of
the latest commit in my repository. This makes it as simple as running
commit-url | pbcopy
to print and then copy the commit URL to my clipboard to
send to my coworkers.
# Get the SHA (e.g. ) of the latest commit in the repository unless a SHA was
# provided as an argument to this script.
commit=${1:-$(git rev-parse --short HEAD)}
# Read the repository base URL from the git config
url=$(git config --get remote.origin.url)
# Take the git@hostname.com:account/repo.git format and turn it into
# https://hostname.com/account/repo/commit/...
if [[ "$url" != "https://"* ]]; then
url=$(echo $url | sed 's/\.git$//' | sed 's/:/\//' | sed 's/^git@/https:\/\//')
fi
echo "$url/commit/$commit"
Built-in copying
This script works great and while it’s not something I have to use all the time,
it’s so nice to have it handy when I need it. However, it is a little bit of a
pain to have to always add | pbcopy
when calling the script if I want to copy
it, so I started to employ a pattern with scripts like this one where I would
create an associated “helper” script that would be named the same with a !
as
a postfix. This helper script would simply call the main script and pipe the
output through pbcopy
automatically.
commit-url $1 | pbcopy
While it looks a little odd to have the exclamation point when running the
command (commit-url!
), it’s nice that several of my scripts are complementary
in this way.
View package.json contents
This one might sound a little odd, but it’s actually quite handy when combined
with autocompletion. As a Node.js developer, I work with package.json
files
all the time. When moving between projects, I don’t always remember what scripts
are available to start the project, run tests, etc. That’s where this script
comes in handy.
# Check if there is a package.json file in the current directory
if [[ -f package.json ]]; then
# Parse the package.json file with jq
jq ".$1" package.json
else
echo -e "Error: Couldn't find a package.json file in the current directory."
fi
At its most simple level you can print the contents of the package.json file by
simply running pkg
. However, if you add an argument you can drill down into a
specific section such as pkg scripts
which would print only the scripts. Very
simple, yet very useful.
Finding URLs in text
Sometimes, I have a piece of text that contains one or more URLs that I wish to extract. With a few lines of bash, this is a very simple task.
# Loop through each line of the input stream
while IFS= read line; do
# Print URLs matching the regex pattern
echo $line | grep -oE 'https?://\S+'
done
Just like commit-url
, I employ a similar concept where I can use url!
to
automatically open the URLs found in the text.
while IFS= read line; do
echo $line | url | xargs open
done
Sound test
This one is really simple, and useful when setting up a new external device like
a speaker or headphones. Rather than opening YouTube or Spotify to see if sound
is working properly, run this script which I have named ding
to send a simple
push notification with sound. This is exclusive to macOS, but the concept could
easily be ported to other operating systems.
osascript -e 'display notification "Did you hear it?" with title "Sound test" sound name "Glass"'
Wrapping up
There is a lot more that could be said about shell scripting and bash, as well as the myriad of other ways to automate your workflow (which I plan on writing other posts about). I hope this article will inspire you to spend some time exploring shell scripting to automate your workflows and improve your productivity.