upvote
Yo, author here.

You are very much correct and I 100% agree with you, I have updated the first example to include a snippet where a proper env-var is used to show of the automatic diagnostic.

Thanks for your feedback, much much appreciated!

reply
For a short-lived script, the `${1:?missing argument}` stuff may be useful, but usually, I want to print some longer usage or help text in the error case.

I usually go with something like this:

  set -eu
  
  function eusage() {
    echo "Usage: $0 <input-file> <output-file>" >&2
    echo "Error: $@" >&2
    exit 1
  }

  infile=${1:-}; shift || eusage "Missing input filename"
  outfile=${1:-}; shift || eusage "Missing output filename"
The `${1:-}` in this case evaluates to an empty string if `$1` is not set, but `shift` fails when there is no argument to remove.
reply
deleted
reply
Agreed; author does note

> Why use the null-command when I could do VAR=${VAR:-default-value}?

and points out it's one less thing to typo, but that assumes the name is the same; I like e.g.

  TARGETFILE="${1:?need input file}"
  OPTIONALVAL="${2:-defaultvalue}"
reply
deleted
reply
"Shortcuts" like :? that tie together two unrelated things (checking a variable for a condition, expanding the value of that variable) drive me up the wall. It makes expressing just one of the two things harder than expressing both, leading to contortions when you want just one, like this use of :.
reply
I use this for setting overridable defaults (this should hopefully actually be in the article I haven't read yet)

: ${DEBUG:=false}

debug is not only false, but garanteed to be set to something so that elsewhere the places that use it don't need extra syntax and checking in case it's empty, and yet you can just set it from the parent environment to override without touching the script or adding a commandline args parser.

And do me, reading this is almost as easy on the brain as just plain DEBUG=true.

Even if you aren't familiar with the extra syntax, like you're someone else in the future who needs to look at it, the two important words pop out, and probably don't mean NOT because whatever those extra bits mean, there's no !. So you get the idea well enough & cruise on.

...[edit] yep it's in the article. but one thing isn't, exactly

    condition && {
        then-cmd   # might exit > 0
        :          # ensure this block ends true
    } || {
        else-cmd
    }
In other words, maybe you should have figured out some other way to write the whole construct, but IF you want to write the if/else this way maybe for just readability or organization, and you want the else-block to only hinge on the initial condition and not also on whatever the then-block might do, then you need a safety-true at the end of the then-block.
reply
[dead]
reply