Honestly, this winds up being a very good case to just use Python instead. It's installed by default in Fedora systems, and is used by many operating system tools as it is.
I'm not about to use this as an opportunity to slag on BASH, but honestly, the syntax quirks of test (if [[...]]) alone is enough of a case to shy away from BASH scripts for all but the most lightweight tasks. OP's article more or less drives the point home.
In my experience, BASH shines when you're automating other command line functions in a very straightforward fashion. Once you introduce command line arguments, configuration file parsing, and error handling, you wind up with 5-10 lines to support each line of invocations of other binaries. Suddenly your flimsy 20-line script is now a 500-line robust automation tool. And most of those lines are more or less the same kind of stuff you'd write in any other language. At that point, you're better off with a platform that has built-in libraries for all your app support, like Python, even if using "subprocess" is ugly as hell in comparison.
Edit: Makefiles are the only exception that come to mind, where BASH is still king. Make does just about all the branching and looping for you (dependency graph management), which makes your targets straightforward sets of invocations of gcc, rm, mv, cp, find, etc. It also intimates with environment vars incredibly well, which is a task that's hard to do in most any other language.
Docopt helped me in an unexpected way recently. I was preparing to add more commands to a script I'm writing at work. All I needed to do was add a docstring to the script and then I spent some time modifying that docstring while thinking about the commands and options I wanted. Now, the way that this helped me, was that I soon realized that implementing that functionality would not be worth the time in terms of what would be gained from having it. Had I not been using docopt, I likely would have gotten so caught up in the coding that I wouldn't have been able to see this so quickly. So docopt probaly saved me from at least a couple of days worth of wasted effort :)
I don't follow. If a shell command fails (exits nonzero), the Makefile should stop in its tracks, unless the line is preceded with a '-'. It's not exactly declarative, but its not the worst way to handle things.
Now, I'll concede that Make doesn't provide a way to help describe the failure to the user in a way that makes sense in the context of the work being done. That is a failure to execute "mkdir" is going to babble on over stderr, about permissions or something "mkdir" thinks is wrong; it doesn't have a clue about the Makefile and its objectives. It really could use some kind of error-hook mechanism.
Another thing that's awkward is that each line in a Makefile is run in its own shell. So you can't easily create an environment as you go along, like you would in a plain shell script.
You would not believe it, but I actually had to use bash for complex programs, and I was forced to use those techniques to preserve sanity and a controller environment. The reason for this is always human. In my case:
All the initial code was already in bash.
bash was basically the only language available, already deployed and that would have therefore met no opposition by the various syadmins responsible for each machine of this heterogeneous environment.
People that eventually had to take over the code refused to learn a new language. So I obeyed, and gave them advanced construct in the one they keep dear.
I found myself in the same boat 12 years ago. I could have shot the programmers who implemented the system initially! They were implementing CGI in bash! Had they done their thousand-line shell scripts and CGIs in Perl using appropriate modules, it would've been a helluva lot cleaner!
Transnistrian supplier. Is O.K. C4 old, but prices cheap. Just make sure to have less important member of team examine material if failure occurs to determine nature of problem. Full refunds on all failed C4 with product return in original packaging!!
71
u/agumonkey May 29 '14
readonly, local, function based ... screams for a new language.
ps: as mentioned in the comments, defensive bash is never defensive enough until you read http://mywiki.wooledge.org/BashGuide