It isn’t a rare occasion that I decide to automate (or contemplate automating) a task in some workflow at work (or even at home). In fact I think it’s a great way to exercise my programming skills and save time getting future tasks done (if only this automation worked with chores). However, I still have my doubts about the latter part of that last statement since I tend to spend many hours and in some cases, days tweaking, perfecting and debugging some script I hobbled together just to fit some task. Four hours in, knee-deep in the debug process, and 3 cups of tea later, the thought of: “is this really worth it?”, pops into my head. Is writing this little script going to save me that much time? Usually this thought gets pushed aside and I root out the bugs, find the usefulness in the new tool I built and generally just forget that I blew hours and a sleepless night or two. The one consolation of these mini projects is that I definitely learn something new and to me in the end is worth it…except maybe when I realize I have been wasting a lot of time.
Today the urge came over me to automate something, specifically REST API calls from my local machine. Lately I have been using the curl command line tool to perform my REST API calls to all sorts of various services at my company. It is becoming so useful to pull data for a service as opposed to visiting the page, logging in with my credentials, and dig around through the menus and submenus. Since I spend most of my time in my terminal, these calls are a huge convenience, but it comes at a cost of typing a lot of arguments into the call. Specifying the hostname, the call type, all the headers and then having to rewrite the path every time I want to do a new request just adds up.
I am not going to go into the details of what I did since this post isn’t about that (that post may come later), but instead about getopt and getopts. These are shell functions that are commonly used to parse command flags passed to a shell script. I only recently stumbled onto this today while ironically debugging a script written by someone else. The idea had never really dawned on me that perhaps someone already wrote some functions for parsing command flags and that rolling my own may not be necessary.
Trolling the web for some decent examples I came across so many conflicts about whether I should be using “getopt” or “getopts”. Below is a list of what I gathered in general:
- Older version (developed in the early 1980’s)
- Handles short and long arguments
- Supposedly mis-handles white-space and empty arguments
- Runs in compatibility mode on most *nix environments (not sure what kind of hinderance this is yet)
- Some would like to imagine it never existed: “Never use getopt(1). getopt cannot handle empty arguments strings, or arguments with embedded whitespace. Please forget that it ever existed.”
- Newer version (developed/introduced in 1986)
- Only handles short arguments
- More portable (compatibility across more *nix environments)
- Standardized by POSIX
Digging up all these facts and attempting to find some good examples, I realized that the usage of getopt(s) is probably one of those long-standing battles similar to Vi(m) vs Emacs or Apple vs Microsoft. With this in mind, there is probably not a right answer, but instead it is probably dependent on a case by case need (and maybe comfort). This of course didn’t help me since I tend to lean towards the newer tools for compatibility, but I did want the long argument support…in the end the compatibility won (coupled with the abundance of good examples for usage).
After slaying some bugs the script was finished and nicely tucked into my “tool belt” with all the others I have developed over time. Coming out of the fray of this made me realize how much time I could have been saving by using one of these functions as opposed to all the days and hours I usually spent rolling my own parser…in a few short hours I was able to roll out a new tool where I was able to focus on the core functionality instead of fixing the parsing of inputs, commands, flags and the whitespace. Now the question is: should I go back and update all those scripts I spent so much time and lost so much sleep over?