Earlier quoted context omitted.
avoid read-while loop... there are problems with filenames starting/ending with spaces... better use find ... -print0 | xargs -0 ... [eventually with -n1]
And you need non-standard feature `-print0` and `xargs -0` there. Better way should be `find ... -exec cmd {} +`.
Defensive BASH programming
41–50 of 53 posts
Re: Defensive BASH programming
#42Re: Defensive BASH programming
#43Earlier quoted context omitted.
While not as common as nounset and errexit, pipefail is a useful option as well (set -o pipefail). Using pipefail, if any program in a pipeline fails (i.e. exit code != 0), then the exit code for the pipeline will be != 0. E.g. pipefail can be useful to ensure `curl does-not-exist-aaaaaaa.com | wc -c` doesn't exit with exit code 0..!
You can set all three of them in a single line. Set up your Bash template with this today: set -o nounset -o pipefail -o errexit
set -eu -o pipefailRe: Defensive BASH programming
#44The only thing in this post that can be accurately called defensive is the use of "local" and "readonly". The rest is all just style preferences, which are rather subjective, and none of which are very appealing to me. Three real defensive bash programming tips are: - Quote all uses of variables - set -o nounset - set -o errexit And many others can be found in and around http://mywiki.wooledge.org/BashFAQ
#!/...
set -eu
# ... Main part of your script ...Re: Defensive BASH programming
#45The only thing in this post that can be accurately called defensive is the use of "local" and "readonly". The rest is all just style preferences, which are rather subjective, and none of which are very appealing to me. Three real defensive bash programming tips are: - Quote all uses of variables - set -o nounset - set -o errexit And many others can be found in and around http://mywiki.wooledge.org/BashFAQ
Note that this can be shortened to "-e" and "-u": #!/... set -eu # ... Main part of your script ...
The latter makes it clearer exactly what features are being enabled, and it's a bit of a false economy to try and "shorten" the script like this.
Re: Defensive BASH programming
#46Any sufficiently-complex shell script can usually be written clearly as a Python or Perl program for instance, without having to worry about how the code might be misinterpreted.
Yes, I write shell scripts sometimes. I just make sure they're doing something pretty straightforward.
Re: Defensive BASH programming
#47Very interesting article and I agree with most of the points. One point I strongly disagree is what is called "Code clarity" where the author replaces conditional expressions ( https://www.gnu.org/software/bash/manual/html_node/Bash-Cond... ) by function calls. I agree that the function call introduces a better name. The problem is that this name is specific to the author of the script. It replaces a reusable tricky…
It'd be like defining an "and" function and writing
if ( and(conditionA, conditionB) ) {
//do something
}
because "&&" is too confusing. It's just syntax. Learn it.And on the subject of &&, it's interesting that in his example about clarity he chooses to use short-circuit and for brevity instead of the more readable if block.
Re: Defensive BASH programming
#48Earlier quoted context omitted.
You might have been better off reading the text after the code example that came after the code you quoted. The text read: - Second example is much better. Finding files is the problem of temporary_files() and not of main()’s. This code is also testable, by unit testing of temporary_files(). - If you try to test the first example, you will mish mash finding temporary files with main algorithm.
The problem isn't where it is - using "ls" to find files is never a good idea from my understanding. I think it's because of ls garbling file names but I might be mistaken there. That the author is using that to find files is reasonable enough to me to disregard the rest of the blog. edit: take that back...looked through rest of blog but don't see anything useful. I hate his idea for functions for builtins, using loc…
https://google.github.io/styleguide/shell.xml?showone=Use_Lo...
Re: Defensive BASH programming
#49Earlier quoted context omitted.
You can set all three of them in a single line. Set up your Bash template with this today: set -o nounset -o pipefail -o errexit
I usually shorten this to: set -eu -o pipefail