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.