My number one wishlist feature was a simple library system. Essentially just let me source files by name by searching in some standard user location. I actually wrote and submitted patches for this but it just didn't work out. Maintained my own version for a while and it was nice but not enough to justify the maintenance burden. Bash's number one feature is being the historical default shell on virtually every Linux distribution, without that there's no point.
At least we've got shellcheck.
I've written a little about how we can more or less accomplish something like meaningfully-reusable shell libraries in the nix ecosystem. I think https://www.t-ravis.com/post/shell/the_missing_comprehensive... lays out the general idea but you can also pick through how my bashrc integrates libraries/modules (https://github.com/abathur/bashrc.nix).
(I'm just dropping these in bin, since that works with existing search path for source. Not ideal, but the generally explicit nature of dependencies in nix minimizes how much things can leak where they aren't meant to go.)
This seems to be posted once per year (at least); however, hardly a complaint as the discussion tends to be high quality.
My personal mantra is if it's over 10~20 lines, I should arguably be using another language, like Python (and perhaps correspondingly, subprocess [2], if I'm in a hurry).
[1] https://web.archive.org/web/20140523002853/http://redsymbol....
These days I've settled on https://www.nushell.sh/
bash introduced an option to respect rather than ignore errors within command sub processes years ago. So if you want to be safer, do something like:
#!/bin/bash
set -euo pipefail
shopt -s inherit_errexit
That works as-is in OSH, which is part of https://oils.pub/(edit: the last time this came up was a year ago, and here's a more concrete example - https://lobste.rs/s/1wohaz/posix_2024_changes#c_9oo1av )
---
But that's STILL incomplete because POSIX mandates that errors be LOST. That is, it mandates broken error handling.
For example, there what I call the "if myfunc" pitfall
set -e
my-deploy-func # errors respected
if ! my-deploy-func; then # errors lost
echo failed
fi
my-deploy-func || echo fail # errors lost
But even if you fix that, it's still not enough.---
I describe all the problems in this doc, e.g. waiting for process subs:
YSH Fixes Shell's Error Handling (errexit) - https://oils.pub/release/latest/doc/error-handling.html
Summary: YSH fixes all shell error handling issues. This was surprisingly hard and required many iterations, but it has stood up to scrutiny.
For contrast, here is a recent attempt at fixing bash, which is also incomplete, and I argue is a horrible language design: https://lobste.rs/s/kidktn/bash_patch_add_shopt_for_implicit...
[edit]
Per the link you posted osh treats a -13 result as success with sigpipe_status_ok, but I'm still interested in your thoughts on if pipefail is better or worse to recommend as "always on" for bash.
set -e
[ -f nonexistent ] && do_something
echo 'this line runs'
but set -e
f(){ [ -f nonexistent ] && do_something; }
f
echo 'This line does not run'
modulo some version differences.Shellcheck isn't a complete solution, and running -e mode is essential to smaller bash files. Shellcheck even knows if a script is in -e mode or not.
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
It reminds me when I wrote a lot of Perl: #!/usr/bin/perl
use strict;
use warnings;
I also prefer --long --args everywhere possible and a comment on any short flag unless it's incredibly common.I've been writing all my Bash scripts like this for ~15 years and it's definitely the way to go.
The short args are great for when you’re typing into a terminal. But when you’re writing and saving a script, be descriptive! One of the most irritating things about bash (and Linux, I guess?) is how magical all the -FEU -lh 3 -B 1 incantations are. They give off a vibe I call “nerd snobbish” where it’s a sort of “oh you don’t know what that all means? How fretful!”
Always, always unless the script is guaranteed to not be portable to other platforms:
#!/usr/bin/env bash
...
set -Eeuo pipefail
It's missing -E to respect traps.
deathanatos•1h ago
Other than that, yeah, if you must use bash, set -eu -o pipefail; the IFS is new and mildly interesting idea to me.
> The idea is that if a reference is made at runtime to an undefined variable, bash has a syntax for declaring a default value, using the ":-" operator:
Just note that defaulting an undefined variable to a value (let's use a default value of "fallback") for these examples is,
The syntax, means "use 'fallback' if foo is unset or is equal to "". (The :, specifically triggers this; there's a bunch of others, like +, which is "use alternate value", or, you'll get the value if the parameter is defined, nothing otherwise. And similarly, will emit triggered if foo is set and not empty.)See "Parameter Expansion" in the manual. I hate this syntax, but it is the syntax one must use to check for undefined-ness.
xelxebar•47m ago
> Python is a great scripting language, and won't blow your foot off if you try to iterate through an array.
I kind of hate that every time the topic of shell scripting comes up, we get a troop of comments touting this mindless nonsense. Python has footguns, too. Heck, it's absolutely terrible and hacky if you try to do concatenative programming with it. Does that mean it should never be used?
Instead of bashing the language, why not learn bash the language? IME, most of the industry has just absorbed shell programming haphazardly through osmosis, and almost always tries to shove the square pegs of OOP and FP into the round hole that is bash. No wonder people are having a bad time.
In contrast, a data-first design that heavily normalizes data into line-oriented tables and passes information around in pipes results in simple, direct code IME. Stop trying to use arrays and embrace data normalization and text. Also, a lot of pain comes from simply not learning the facilities, e.g. the set builtin obviates most uses of string munging and exec:
Anyway, the senseless bash hate is somewhat of a pet peeve of mine. Exunt.3eb7988a1663•27m ago
C/C++ got us really far, but greenfield projects are moving to safer languages where they can. Expert low level programmers, armed with all of the available linting tools are still making unfortunate mistakes. At some point we should switch to something better.
oguz-ismail•18m ago
Agree. Python isn't it though