My brain parses that || as quickly as it verifies the !, and having the actual command at the left of the line is helpful for clarity; FWIW, this is actually a pretty common paradigm in many languages including Ruby--with "or die"--which people generally liked for cute syntax.
Re:Elegant Bash Conditionals
by castillar76 on Tuesday March 02, 2021 @03:48PM
(#26320439)
Yep, this was a common Perl construct as well, since you could follow "or die" with a custom error string. I used to amuse myself (way back in the Stone Age, when I was in college and didn't know better) by using amusing and unique invectives for error messages like 'or die "you son of a motherless goat"'. Not only did they make me giggle a little, they made searching code for the line that failed a little easier...
Yeah yeah yeah, but citing Perl to defend that something is readable doesn't win arguments ;P.
Re:Elegant Bash Conditionals
by ycombobreaker on Wednesday March 03, 2021 @02:54AM
(#26325823)
What did Larry Wall do to deserve that? Ruby cribbed the "or die" idiom (and others) from Perl because they were useful. At least let him own his good ideas along with the rest of the language.
Well, some parts of Perl actually make a lot of sense.
I mentioned that these days I write Go for a living, which involves a lot of:
if err := thingThatMightFail(); err != nil {
...
}
so I was saying that of course I think lots of `if` statements for error handling are reasonable. (Hmm, thinking back, I learned Go in 2012, and my Bash probably peaked in 2013, I wonder if having learned Go made me more amenable to this in Bash.)I think a single-line `cmd || die "msg"` like in Perl or Ruby is handy and fine. Or maybe even a two-line
some command that might fail ||
die "Some message that is long enough that it wants to be its own line"
But once it starts getting to have multiple statements that you're grouping with `{ }`, just use an `if` statement. If I were reviewing someone's Ruby that had multiple lines after the "or" in "or die", I'd tell them to just use unless thingThatMightFail
...
endI think you answered your own question. Those `if` constructs are indeed clunky. In fact I'd venture to say it's really just "C-like language Stockholm syndrome" that makes them feel more "maintainable" or "clear".
The bash "or" syntax reads very clearly. Do X or do Y. Do X or fail like so. It's very English-like and intuitive. And understanding why it works is just a matter of understanding logical operator short circuiting, which you have to understand to work in C-like languages anyway.
Problem is you have to fork subshells if here is any sequencing involved. Compare
if condition ; then
command1
command2
else
command3
command4
fi
versus: condition && (command1; command2) || (command3; command4)
GNU Bash has a fix for that: non-forking braces.
I know someone who wrote most of his Bash that way, using `cmd && { ...; }` instead of `if cmd; then ...; fi` and `cmd || { ...; }` instead of `if ! cmd; then ...; fi`. I never thought it was particularly clear or maintainable--that it was more on the "clever" side than on the "clear" side.
Sure, it's a little clunky to have an `if` for everything that might fail, but uh... these days I write Go for a living.