Bash one liners
I have a graveyard of one-time-use bash one-liners that become either aliases or get wrapped by shell functions in my .zshrc
file. I often justify the effort of polishing them and adding to my dotfiles with the excuse that they will be used again in the future. Even if they are never used again, they serve as a library of examples. For every new command, there is always an old one that did a similar thing.
More importantly, these bash one-liners are really fun to write. What once started as a thought to build a new command line application, was first challenged with a “could it be a simple bash script?” and then finally it was reduced to “could I write it one line?”. It’s like my own personal code golf challenge, where I keep trying to make the line smaller and smaller.
There is also something magical about slowly incrementing your program in a REPL, and piecing the commands individually until I understand how to plug them together in my one-liner. The feedback loop is so satisfyingly quick. You start with a simple command that just parses a list and spits it back to the terminal and then iterate on it. Refining and expanding it one command at a time.
Unmaintained go.mod
dependencies
Today I had an itch I had an urge to scratch scratch: to figure out how many of the dependencies in a go.mod
file were repositories that are likely no longer maintained and how many stars they had.
This is the magic one-liner:
for repo in $(cat ./go.mod | grep "\tgithub.com/" | sed 's/\t//' | sed 's/\ v.*//' | sed 's|github\.com/\([^/]*\/[^/]*\).*|\1|p' | uniq); do; printf "Last commit: %10s | %5s ⭐ | %s\n" "$(gh api /repos/$repo/commits | jq -r '.[0].commit.author.date' | sed 's/\(.*\)T.*/\1/')" "$(gh api /repos/$repo -q '.stargazers_count')" "github.com/$repo"; done;
Important to note: this command uses GitHub’s command line application gh
. If you are running this yourself, make sure to authenticate with gh auth
.
Results on gohugoio/hugo’s go.mod file
Command breakdown:
grep "\tgithub.com/"
to take only the repositories URLs from the file.sed 's/\t//' | sed 's/\ v.*//'
will remove the prefixed tab character and suffixed version annotations.sed 's|github\.com/\([^/]*\/[^/]*\).*|\1|p' | uniq
is a regex that will extract only the repository part of the GitHub URL. I.e. we only want theOWNER/REPO
portion. If the go dependency has anything after that (e.g./v2
) we want to leave that out. This could lead to duplicate repositories to be listed. Hence theuniq
command.gh api /repos/$l/commits
will fetch all the first page commits from the repository.| jq -r '.[0].commit.author.date' | sed 's/\(.*\)T.*/\1/
will print only the commit date and remove the timezone information, leaving a date string formatted such asYYYY-MM-DD
.
gh api /repos/$l -q '.stargazers_count')
prints the number of stars the repository has.printf "Last commit: %10s | %5s ⭐ | %s\n"
formats the data leaving 10 characters for the date field and 5 characters for the number of starts (left padding with spaces).
Maybe next time I’ll record the process of writing the command itself. I’m guessing it would be valuable to look in hindsight the increments made. With this one, they appeared roughly in this order:
- Extracting the list of GitHub dependencies from
go.mod
- Clean the lines and strip unwanted prefixes and suffixes
- Passing the URL to
gh api repo/OWNER/REPO/commits
- Discovering I needed to extract only the
OWNER/REPO
from the URL and that some dependencies had additional suffixes. - Battling with the strings until I got a regex that extracted only the part I wanted
- Wrapping the command in a
for
loop to make it easier to parameterize the repo name - Add
jq
command to extract commit date and stargazers - Format strings
⇦ Back Home | ⇧ Top |
If you hated this post, and can't keep it to yourself, consider sending me an e-mail at fred.rbittencourt@gmail.com or complain with me at Twitter X @derfrb. I'm also occasionally responsive to positive comments.