5 ms·
Some tips of my own: - It's almost always preferable to put `-u` (nounset) in your shebang to cause using undeclared variables to be an error. The only excepti
by mr-wendel 3y ago
Some tips of my own:
- It's almost always preferable to put `-u` (nounset) in your shebang to cause using undeclared variables to be an error. The only exception I typically run across is expansion of arrays using "${arr[@]}" syntax -- if the array is empty, this is considered unbound.
- You can use `-n` (noexec) as a poor-man's attempt at a dry-run, as this will prevent execution of commands.
- Also handy is `-e` (errexit), but you must take care to observe that essentially, this only causes "naked" commands that fail to cause an exit. Personally, I prefer to avoid this and append `|| fail "..."` to commands liberally.
- Calzifer 3y ago> to put `-u` (nounset) in your shebang Any particular reason why in the shebang instead of set -u? > The only exception I typically run across is expansion of arrays using "${arr[@]}" syntax In Bash? Works for me. Edit: another comment mentions it as well. Seem to behave better in newer versions of Bash and only problematic in <= 4.3 https://news.ycombinator.com/item?id=38397241 https://news.ycombinator.com/item?id=38397241 $ bash -uc 'unset x; echo "=> ${x[@]}"' => $ bash -uc 'x=(); echo "=> ${x[@]}"' => $ bash -uc 'x=(); echo "=> ${x[0]}"' bash: x[0]: unbound variable Zsh does not like the first example but both should support: $ bash -uc 'unset x; echo "=> ${x[@]:-null}"' => null > Also handy is `-e` (errexit), It is unfortunately very confusion with functions. Made me like it less over the years.
- mr-wendel 3y agoUsing the shebang just helps highlight the fact that the rule is in use globally, but otherwise has no advantage to using `set -u`. The clarifications on `-u` and arrays are useful. I'm definitely used to assuming newer (... non-ancient?) versions of Bash are what is available.
- Xophmeister 3y agoUsing `set -u` is more portable. If your shebang is `/usr/bin/env bash`, which it probably should be, then you can't add additional command line arguments in Linux with older coreutils. macOS supports additional arguments, regardless, and in Linux, coreutils 8.30 added the `-S` option to `env` to get around this problem.
- augusto-moura 3y agoThe problem with "${arr[@]}" only exists on bash 3 and before, since bash 4, [@] will never throw unbound variables even in cases where the variable is truly undefined. This is still a problem however, because macOS, to this day, still installs bash v3 by default and doesn't update it automatically (absolute madness, the last release of bash 3 it's from 20 years ago!). In any case, you can workaround expanding empty arrays throwing unbound by using the ${var+alter} expansion echo "${arr+${arr[@]}}"
- mmsc 3y agoThe problem with "${arr[@]}" only exists on bash 3 and before, since bash 4 4.4 fixed it: $ bash --version GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu) $ declare -A arr $ set -u $ "${arr[@]}" -bash: arr[@]: unbound variable
- augusto-moura 3y agoAh, that's true, I couldn't recall which version fixed it. Usually I assume v4 because any other distro automatically updates to the latest v4 version or latest version af all. macOS is the only one out there missing on this. The other big feature that was only added after bash 3 and is missing on mac is associative arrays
- extraduder_ire 3y ago> macOS, to this day, still installs bash v3 by default and doesn't update it automatically (absolute madness, the last release of bash 3 it's from 20 years ago!). GPL3, buddy. You can use brew to install a newer version and somewhat hide the old one.
- anamexis 3y agoRegarding the `-e` issue, this is well handled by `-o pipefail`, which as of last year is part of POSIX.
- extraduder_ire 3y agoI find that I usually have to use traps when I put use options to terminate the script early, mostly when I have some files to clean up. "trap" is a great scripting feature that doesn't get talked about enough, IME.
- bruce_one 3y agoOne common suggestion is to not set Bash/shell options in the shebang because if someone runs the script with the interpreter explicitly (e.g. `bash my_script.sh`, rather than `./my_script.sh` (which, ime, is quite common as many people to seem to do it to avoid setting the execute bit, sometimes due to a lack of understanding ime)) then the options won't apply - which isn't fun... Using `set` (e.g. `set -euo pipefail` as the first line after the shebang) is a common suggestion due to this, and similarly it helps with the `#!/usr/bin/env bash` case where the shebang can't handle additional arguments :-)