I’ve seen this post – https://thoughtbot.com/blog/the-unix-shells-humble-if and there was no place for comments. Here is my humorous response then.
( Below: removed added )
The Unix shell is often overlooked by software developers (many times for good reasons) more familiar with higher level (read normal / saner / better / actually designed and not accidental) languages. This is unfortunate because the shell can be one of the most important parts of a developer’s toolkit best sources of WTFs. From the one-off grep search or sed replacement in your source tree (by commands having zero semantic understanding so applicable to only basic cases) to a more formal script for deploying or backing up an entire application complete with options and error handling (don’t even start about error handling in shell), the shell can be a huge time saver (or waster).
To help shed light on the power and subtlety (read surprise mada**er) that is the Unix shell, I’d like to take a deep dive into just one of its many features: the humble if statement.
The humble if statement has only two possible branches and doesn’t throw exceptions. Look how amazing it plays out as opposed to normal programming languages in the following examples.
…
if grep -Fq 'ERROR' development.log; then
# there were problems at some point
elif grep -Fq 'WARN' development.log; then
# there were minor problems at some point
else
# all ok!
fi
In the example above, else branches are taken when there was no match in the file, right? Right.
But… if is so humble and primitive that it only knows about two exit codes: zero for OK and non-zero for … not OK. grep returns exit code one if the pattern was not found and exit code two if there was an error (syntax error, file not found, etc.). So the else branches are taken if there was no match OR there was an error running grep. Process this for a moment.
If your command is a pipeline, the exit status of the last command in the pipeline will be used (meaning that any errors by previous commands in the pipeline such as specifying wrong file will be ignored and the final grep will just report that it didn’t find the pattern):
# useless use of cat for educational purposes only!
if cat development.log | grep -Fq 'ERROR'; then
# ...
fi
For the most whole part, this is intuitive and expected one of the many bombs in the shell’s minefield. In cases where it’s not, some shells offer the pipefail option afterthought to change that behavior to something more resembling normal programming languages.
I’ll stop here for the brevity. The idea should be clear by now 🙂
Have a nice day!
Leave a comment