Indeed, echo can fail. Redirecting stdout to /dev/full is probably the easiest way to make this happen but a named pipe can be used if more control is required. The sentence from the article “The echo command always exists with 0” is untrue (in addition to containing a typo).
Or &&true at the end, if it’s okay for this command to fail. EDIT: see replies
It’s as much of a kludge as any other, and I’m not sure how to save the return value of a command here, but bash -ec 'false && true; echo $?' will return 0 and not exit from failure. EDIT: it echoes 1 (saving the return value), see replies for why.
I did mean || true, but in the process of questioning what was going on I learned that && true appears to also prevent exit from -eand save the return value!
Echoes 3. I used a function and return to prove it isn’t simply a generic 1 from failure (as false would provide). Adding -x will also show you more of what’s going on.
I personally use the following formatting, which flips the logic, uses a builtin, and printd to stderr.
[ "${USER}" == "root" ] || {printf "%s\n" "User must be 'root'" 1>&2; exit 1; }
When I start doing a larger amount of checks, I wrap the command group within a function, which turns into the following, and can optionally set the exit code.
die() { printf "%s\n" "${1}" 1>&2; exit ${2:-1}; }
...
[ "${USER}" == "root" ] || die "User must be 'root'"
This article leaves aside the most useful special parameter for elegant conditional: the “most recent argument”, $_.
Example of use: test -f /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh && source $_ || echo "zsh-syntax-highlighting not installed" >&2
Nothing elegant about this, just less verbose, and IMHO, less readable. Either future you after six months or someone willing to contribute to your project who is not that familiar with sh, and all to save some lines?
For me this is on the same line as -s vs –short flags. Long flags are for scripts, short flags are for the cli. As if I myself would glance over a script and know what wget -k does instead of wget –insecure (example).
Every line state clearly what’s going on. This is quite functional style alike. Removing the verbosity of the if statement gives succinctness and clarity to the code.
Personally to increase clarity I do use a basic convention for variables and methods :
Prefixes
is | has := return or contains a bool
do := perform an action
on := trigger on event
Eg:
isValidTag()
&& isNotEmptyTag()
&& hasLessThan5Tags()
&& doAppendTag()
test -f FILE && source $_ || echo "FILE does not exist" >&2
This doesn’t work if the filename has a space or an asterisk in it. You need to surround $_ with double-quotes. https://www.shellcheck.net/ is your friend.
assuming it was added based on @Diti ‘s comment above, it would work for the intended shell, zsh since zsh doesn’t expand unquoted variables the same. I agree the author should probably update this.
Anecdotally, I have polled the developers where I work whether they prefer the slick && conditional or the straightforward verbose if statement. The results overwhelmingly favor the if statement. These are devs experienced with bash, so this doesn’t even consider that:
I’ve always felt a bit uneasy about this one. I mean, what if echo fails? :-)
So I usually do
instead… just to be safe.
Indeed, echo can fail. Redirecting stdout to /dev/full is probably the easiest way to make this happen but a named pipe can be used if more control is required. The sentence from the article “The echo command always exists with 0” is untrue (in addition to containing a typo).
Don’t you need
set +e;
beforeecho
, just to be extra safe?I had to look that up.
set +e
disables the-e
option:That’s not enabled by default, though, and I personally don’t use it.
Or
&&true
at the end, if it’s okay for this command to fail. EDIT: see repliesIt’s as much of a kludge as any other, and I’m not sure how to save the return value of a command here, but
bash -ec 'false && true; echo $?'
will return0
and not exit from failure. EDIT: it echoes 1 (saving the return value), see replies for why.You probably mean
|| true
. But yeah, that works!I did mean
|| true
, but in the process of questioning what was going on I learned that&& true
appears to also prevent exit from-e
and save the return value!E.G.,
Echoes
3
. I used a function andreturn
to prove it isn’t simply a generic1
from failure (asfalse
would provide). Adding-x
will also show you more of what’s going on.I personally use the following formatting, which flips the logic, uses a builtin, and printd to stderr.
[ "${USER}" == "root" ] || {printf "%s\n" "User must be 'root'" 1>&2; exit 1; }
When I start doing a larger amount of checks, I wrap the command group within a function, which turns into the following, and can optionally set the exit code.
I also always print to standard out, but I’m pretty sure most shells have echo as a built-in. The form I usually use is
[Comment removed by author]
This article leaves aside the most useful special parameter for elegant conditional: the “most recent argument”,
$_
.Example of use:
test -f /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh && source $_ || echo "zsh-syntax-highlighting not installed" >&2
Even
😎
TIL. Thank you for sharing, I never knew that one.
Brilliant! Wasn’t aware. Added it in the post.
Nothing elegant about this, just less verbose, and IMHO, less readable. Either future you after six months or someone willing to contribute to your project who is not that familiar with sh, and all to save some lines?
For me this is on the same line as -s vs –short flags. Long flags are for scripts, short flags are for the cli. As if I myself would glance over a script and know what wget -k does instead of wget –insecure (example).
I believe this turn to be quite readable instead. Take a look at this:
Every line state clearly what’s going on. This is quite
functional style alike
. Removing the verbosity of theif
statement gives succinctness and clarity to the code.Personally to increase clarity I do use a basic convention for variables and methods :
I think the if statement style is at least as easy to read if not easier:
This doesn’t work if the filename has a space or an asterisk in it. You need to surround
$_
with double-quotes. https://www.shellcheck.net/ is your friend.assuming it was added based on @Diti ‘s comment above, it would work for the intended shell, zsh since zsh doesn’t expand unquoted variables the same. I agree the author should probably update this.
Anecdotally, I have polled the developers where I work whether they prefer the slick
&&
conditional or the straightforward verboseif
statement. The results overwhelmingly favor theif
statement. These are devs experienced with bash, so this doesn’t even consider that:All of these also seem to work in POSIX sh, just FYI.