In zsh, you can do:
var=${$(cmd):-default}
But in any POSIX-like shell including bash, you can always do:
var=$(cmd)
var=${var:-default}
Or
: "${var:=default}"
You do lose the exit status, but you could save it in a variable in between the two steps:
var=$(cmd)
exit_status=$?
: "${var:=default}"
You can also do things like:
var=$(cmd) exit_status=$? || var=default
For $var
to be set to default
if cmd
failed (regardless of whether it output something or not).
Note that if cmd
output is non-empty but consists only of newline characters, then after var=$(cmd)
, $var
will still be empty as command substitution strips all trailing newline characters. bash
also strips all NUL characters. zsh
preserves them, some other shells strip everything after the first NUL character. yash
chokes on sequences of bytes not forming valid characters in the locale.
For $var
to be set to default
only if cmd
's output is non-empty, with GNU grep
(or any implementation that can cope with (and not modify) non-text input, and doesn't ignore non-delimited lines), you can do:
var=$(cmd | grep '^') || var=default
where grep '^'
returns true if it finds the beginning of at least one line in its input (and passes its whole input undisturbed to its output).
In that case, cmd
's exit status is lost. $var
could end up being empty if cmd
outputs only NULs or newlines.
c=${a:=b}
would assign to botha
andc
, which might be a bit confusing to a reader. (I don't think the linked question had that either.) The one that doesn't assing toa
isc=${a:-b}
.