lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Shell scripting bafflement


From: Greg Chicares
Subject: Re: [lmi] Shell scripting bafflement
Date: Thu, 27 Feb 2020 23:13:58 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.4.1

On 2020-02-27 02:38, Vadim Zeitlin wrote:
> On Thu, 27 Feb 2020 00:34:01 +0000 Greg Chicares <address@hidden> wrote:
[...]
> GC> Consider the following commands, which
> GC>  - test a resolvable URL vs. one spoiled by adding 'X' after "https://";
> GC>  - with vs. without "$()"
> GC> 
> GC> $if curl https://Xgit.savannah.nongnu.org:443 >/dev/null 2>&1; then echo 
> true; else echo false; fi 
> GC> false
> GC> $if curl https://git.savannah.nongnu.org:443 >/dev/null 2>&1; then echo 
> true; else echo false; fi 
> GC> true
> GC> 
> GC> $if $(curl https://Xgit.savannah.nongnu.org:443 >/dev/null 2>&1); then 
> echo true; else echo false; fi
> GC> false
> GC> $if $(curl https://git.savannah.nongnu.org:443 >/dev/null 2>&1); then 
> echo true; else echo false; fi 
> GC> true
> GC> 
> GC> The effects seem to be the same with or without "$()", so what does the
> GC> the "$()" do in this case? And why does it seem to make no difference?
> 
>  The difference is that you don't use "[" at all here.

Okay, yes, that explains the difference between
  if [ command ]
and
  if [ $(command) ]
, but I'd like to ask a different question: what's the difference between
  if $(curl some_URL >/dev/null 2>&1)
and
  if   curl some_URL >/dev/null 2>&1
? In the examples quoted above, they appear to behave identically. I found
that surprising. I understand that in
  if   curl some_URL >/dev/null 2>&1
the command's return code is 0 or not depending on the URL's reachability.
However, here:
  if $(curl some_URL >/dev/null 2>&1)
I was expecting that
 - the command would be run in a subshell
 - the command's return code would vanish when that subshell returns
 - the command-expansion's return code would be 0 if the subshell
   executed the command
but it seems that the command-expansion's return code is the
command's return code. The bash manual prescribes that:

  
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Simple-Command-Expansion
| If one of the expansions contained a command substitution, the
| exit status of the command is the exit status of the last
| command substitution performed.

but AFAICT POSIX doesn't specify anything:
  
https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03

>  What can I say, nobody ever pretended shell wasn't confusing. IMHO this is
> not the worst part, because typically once you realize the difference
> between "if command" and "if test condition", things should be relatively
> clear.

Yeah. Some languages were designed, and show a coherent set of design
principles. OTOH, other languages (e.g., the shell grammar) have evolved,
like a natural human language.

>  The best advice I can give about shell scripting is to always test
> anything you might have a doubt about in a separate snippet to ensure that
> it behaves as you expect it to, because failures in the actual scripts are
> hard to debug and often lead to unforeseeable weirdness later on.

That's how I came up with this test:
  if [ "$(umask)" -ne 022 ]; then
in lmi commit 135b344eb6d. I always have to look up the syntax for
comparisons like that. (Using 'shellcheck' helps, too.)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]