Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.debian.user > #198913 > unrolled thread

Bash true/false builtings undocumented? "false" not working?

Started byZenaan Harkness <zenaan@freedbms.net>
First post2018-08-17 10:50 +0200
Last post2018-08-23 16:30 +0200
Articles 20 on this page of 21 — 7 participants

Back to article view | Back to linux.debian.user


Contents

  Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-17 10:50 +0200
    Re: Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-17 11:00 +0200
    Re: Bash true/false builtings undocumented? "false" not working? Nicolas George <george@nsup.org> - 2018-08-17 11:00 +0200
      Re: Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-17 11:30 +0200
      Re: Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-17 11:40 +0200
        Re: Bash true/false builtings undocumented? "false" not working? Nicolas George <george@nsup.org> - 2018-08-17 11:40 +0200
        Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-17 12:20 +0200
        Re: Re: Bash true/false builtings undocumented? "false" not working? Clive Standbridge <list-user@tgstandbridges.plus.com> - 2018-08-17 14:10 +0200
          Re: Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-17 15:40 +0200
        Re: Bash true/false builtings undocumented? "false" not working? Greg Wooledge <wooledg@eeg.ccf.org> - 2018-08-17 14:30 +0200
          Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-17 15:50 +0200
            Re: Bash true/false builtings undocumented? "false" not working? Greg Wooledge <wooledg@eeg.ccf.org> - 2018-08-17 16:20 +0200
              Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-17 16:40 +0200
                Re: Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-18 01:10 +0200
          Re: Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-18 01:30 +0200
    Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-17 11:30 +0200
      Re: Bash true/false builtings undocumented? "false" not working? Zenaan Harkness <zenaan@freedbms.net> - 2018-08-17 11:40 +0200
        Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-17 11:50 +0200
          Re: Bash true/false builtings undocumented? "false" not working? tomas@tuxteam.de - 2018-08-17 12:00 +0200
        Re: Bash true/false builtings undocumented? "false" not working? Stefan Krusche <linux@stefan-krusche.de> - 2018-08-23 15:00 +0200
          Re: Bash true/false builtings undocumented? "false" not working? <tomas@tuxteam.de> - 2018-08-23 16:30 +0200

Page 1 of 2  [1] 2  Next page →


#198913 — Bash true/false builtings undocumented? "false" not working?

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-17 10:50 +0200
SubjectBash true/false builtings undocumented? "false" not working?
Message-ID<wnICd-6jg-3@gated-at.bofh.it>
1)
Bash man page largely fails to document the true and false builtins
AFAICT, except for this sentence just under the heading
"^SHELL BUILTIN COMMANDS":

 The :, true, false, and test builtins do not accept options and do
 not treat -- specially.

But whilst the subsequent list of Bash builtin commands DOES include
entries for ":" (the very first entry) and "test", it appears to fail
to include entries for "true" and for "false".

This would not matter so much except for the following:


2)
Why is executing "false" prior to testing it's output, apparently
differen to executing "false" in a pipeline, e.g.:

$ false
$ test $? && echo ok || echo error $?
ok
$ false blah
$ test $? && echo ok || echo error $?
ok
$ false --
$ test $? && echo ok || echo error $?
ok
$ true
$ test $? && echo ok || echo error $?
ok
$ true && echo ok || echo error $?
ok
$ false && echo ok || echo error $?
error 1
$ false blah && echo ok || echo error $?
error 1
$ false 2 && echo ok || echo error $?
error 1
$ false -- && echo ok || echo error $?
error 1
$ builtin false -- && echo ok || echo error $?
error 1
$ builtin false --
$ test $? && echo ok || echo error $?
ok
$ which false
/bin/false
$ /bin/false
$ test $? && echo ok || echo error $?
ok



The above results are perplexing me, and frustratingly
inconsistent!

For example, "man false" says inter alia:

NAME  false - do nothing, unsuccessfully
…
DESCRIPTION  Exit with a status code indicating failure.


The descriptions suggests that /bin/false ought work outside of a
pipeline in the same as way inside a pipeline - vhy, is, eet, not,
so?


TIA,

[toc] | [next] | [standalone]


#198916

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-17 11:00 +0200
Message-ID<wnILU-6mt-9@gated-at.bofh.it>
In reply to#198913
On Fri, Aug 17, 2018 at 06:46:54PM +1000, Zenaan Harkness wrote:
> 1)
> Bash man page largely fails to document the true and false builtins
> AFAICT, except for this sentence just under the heading
> "^SHELL BUILTIN COMMANDS":
> 
>  The :, true, false, and test builtins do not accept options and do
>  not treat -- specially.
> 
> But whilst the subsequent list of Bash builtin commands DOES include
> entries for ":" (the very first entry) and "test", it appears to fail
> to include entries for "true" and for "false".
> 
> This would not matter so much except for the following:
> 
> 
> 2)
> Why is executing "false" prior to testing it's output, apparently
> differen to executing "false" in a pipeline, e.g.:
> 
> $ false
> $ test $? && echo ok || echo error $?
> ok
> $ false blah
> $ test $? && echo ok || echo error $?
> ok
> $ false --
> $ test $? && echo ok || echo error $?
> ok
> $ true
> $ test $? && echo ok || echo error $?
> ok
> $ true && echo ok || echo error $?
> ok
> $ false && echo ok || echo error $?
> error 1
> $ false blah && echo ok || echo error $?
> error 1
> $ false 2 && echo ok || echo error $?
> error 1
> $ false -- && echo ok || echo error $?
> error 1
> $ builtin false -- && echo ok || echo error $?
> error 1
> $ builtin false --
> $ test $? && echo ok || echo error $?
> ok
> $ which false
> /bin/false
> $ /bin/false
> $ test $? && echo ok || echo error $?
> ok
> 
> 
> 
> The above results are perplexing me, and frustratingly
> inconsistent!
> 
> For example, "man false" says inter alia:
> 
> NAME  false - do nothing, unsuccessfully
> …
> DESCRIPTION  Exit with a status code indicating failure.
> 
> 
> The descriptions suggests that /bin/false ought work outside of a
> pipeline in the same as way inside a pipeline - vhy, is, eet, not,
> so?
> 
> 
> TIA,


Could it be that the reason this does not work from the shell prompt
as I expect, is perhaps that my command prompt is successfully
running a command in between, and therefore hiding all error codes?

[toc] | [prev] | [next] | [standalone]


#198917

FromNicolas George <george@nsup.org>
Date2018-08-17 11:00 +0200
Message-ID<wnILU-6mt-13@gated-at.bofh.it>
In reply to#198913

[Multipart message — attachments visible in raw view] — view raw

Zenaan Harkness (2018-08-17):
> But whilst the subsequent list of Bash builtin commands DOES include
> entries for ":" (the very first entry) and "test", it appears to fail
> to include entries for "true" and for "false".

Maybe because it does the same thing as the standard and non-builtin
true and false?

> $ test $? &&

Stop right there. "test $?" does not do what you think it does.

Regards,

-- 
  Nicolas George

[toc] | [prev] | [next] | [standalone]


#198918

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-17 11:30 +0200
Message-ID<wnJeV-6KG-1@gated-at.bofh.it>
In reply to#198917
On Fri, Aug 17, 2018 at 10:51:03AM +0200, Nicolas George wrote:
> Zenaan Harkness (2018-08-17):
> > But whilst the subsequent list of Bash builtin commands DOES include
> > entries for ":" (the very first entry) and "test", it appears to fail
> > to include entries for "true" and for "false".
> 
> Maybe because it does the same thing as the standard and non-builtin
> true and false?
> 
> > $ test $? &&
> 
> Stop right there. "test $?" does not do what you think it does.

Can you please explain what I'm not understanding - clearly I am
missing something. Thank you,

[toc] | [prev] | [next] | [standalone]


#198921

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-17 11:40 +0200
Message-ID<wnJoB-6ND-3@gated-at.bofh.it>
In reply to#198917
On Fri, Aug 17, 2018 at 10:51:03AM +0200, Nicolas George wrote:
> Zenaan Harkness (2018-08-17):
> > But whilst the subsequent list of Bash builtin commands DOES include
> > entries for ":" (the very first entry) and "test", it appears to fail
> > to include entries for "true" and for "false".
> 
> Maybe because it does the same thing as the standard and non-builtin
> true and false?
> 
> > $ test $? &&
> 
> Stop right there. "test $?" does not do what you think it does.

Aha. It's actually the Special Parameter "?", aka "$?" that I did not
understand - I was treating it as a value, when actually it is
something that expands, i.e. into a string, and not something that is
treated as true or false.

D∀nka shøn ⨟⟩


So!  I guess the way to test the EXPANSION of the the most recent
exit status, is to test it as a string value, assuming use of the
token "$?".

Seems clunky.

Is there a "cleaner" way to test the true/ error exit status other
than using "$?", with bonus points for working in posix sh as well as
Bash, ?

TIA,

[toc] | [prev] | [next] | [standalone]


#198923

FromNicolas George <george@nsup.org>
Date2018-08-17 11:40 +0200
Message-ID<wnJoB-6ND-5@gated-at.bofh.it>
In reply to#198921

[Multipart message — attachments visible in raw view] — view raw

Zenaan Harkness (2018-08-17):
> Aha. It's actually the Special Parameter "?", aka "$?" that I did not
> understand - I was treating it as a value, when actually it is
> something that expands, i.e. into a string, and not something that is
> treated as true or false.

That is how all parameters work, not just $?. It seems your problem was
more basic than I expected.

> So!  I guess the way to test the EXPANSION of the the most recent
> exit status, is to test it as a string value, assuming use of the
> token "$?".
> 
> Seems clunky.

That is shell.

> Is there a "cleaner" way to test the true/ error exit status other
> than using "$?", with bonus points for working in posix sh as well as
> Bash, ?

$? is the correct parameter to test, and testing it as a string is
reliable.

You could use expr to make numerical computations, but in this instance
it is completely overkill.

Regards,

-- 
  Nicolas George

[toc] | [prev] | [next] | [standalone]


#198926

From<tomas@tuxteam.de>
Date2018-08-17 12:20 +0200
Message-ID<wnK1k-7fs-13@gated-at.bofh.it>
In reply to#198921
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 07:29:47PM +1000, Zenaan Harkness wrote:
> On Fri, Aug 17, 2018 at 10:51:03AM +0200, Nicolas George wrote:
> > Zenaan Harkness (2018-08-17):
> > > But whilst the subsequent list of Bash builtin commands DOES include
> > > entries for ":" (the very first entry) and "test", it appears to fail
> > > to include entries for "true" and for "false".
> > 
> > Maybe because it does the same thing as the standard and non-builtin
> > true and false?
> > 
> > > $ test $? &&
> > 
> > Stop right there. "test $?" does not do what you think it does.
> 
> Aha. It's actually the Special Parameter "?", aka "$?" that I did not
> understand - I was treating it as a value, when actually it is
> something that expands, i.e. into a string, and not something that is
> treated as true or false.

Everything expands in a shell. There are no "values". Or something :)

Cheers
- -- tomás

> So!  I guess the way to test the EXPANSION of the the most recent
> exit status, is to test it as a string value, assuming use of the
> token "$?".
> 
> Seems clunky.
> 
> Is there a "cleaner" way to test the true/ error exit status other
> than using "$?", with bonus points for working in posix sh as well as
> Bash, ?

Hm. For example:

  true && echo "yep" || echo "nope"

(I know, I know ;-)

But typically, you'd check exit status right "on the spot" (for 'true'
it does look a bit grotty, yes :).

But sometimes you want to keep your exit status for later in the script.

There's more than one way to do it. You can, as you hinted at above,
just squirrel away "$?" and later check it against 0 or not. One
advantage of this is that some programs communicate a bit more through
the exit value (cf curl's man page under "EXIT CODES" for an extreme
example :)

There's another possibility which meshes pretty well with How Shells
Work (TM): squirrel away "true" or "false" in your condition variable:

  test_weather_station && SUNNY=true || SUNNY=false
  # more stuff
  # still more stuff
  # ...
  $SUNNY && echo yeah || echo booh

This works because depending on SUNNY's value, this last line (first)
expands to 'true && echo yeah || echo booh' (or 'false &&...').

Nifty. But if SUNNY's value is 'mumble', you might get an error message
"mumble: command not found" on stderr (and then a "booh" on stdout).

Whereas if SUNNY's value is "rm -Rf /" -- well, this one might have an
exit status of "success", so if the rm succeeds, it will say "yeah".

Caveat Scriptor.

Cheers
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt2n7IACgkQBcgs9XrR2kY4qgCfSnndy0sUdoqxiUMScZZRcWz3
uOAAn2Q+dPILTnJp3HzOqVlqYf1iTm7V
=sAs8
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#198928

FromClive Standbridge <list-user@tgstandbridges.plus.com>
Date2018-08-17 14:10 +0200
Message-ID<wnLJM-8lc-7@gated-at.bofh.it>
In reply to#198921
> Is there a "cleaner" way to test the true/ error exit status other
> than using "$?", with bonus points for working in posix sh as well as
> Bash, ?

test $? -eq 0

"help test" will tell you more.


Another point from your original mail,

> $ false
> $ test $? && echo ok || echo error $?

The second $? in that line is different from the first; it's the exit
status of "test". That can be demonstrated, with a corrected test
command, by

$ grep stuff /no/such/file
grep: /no/such/file: No such file or directory
$ echo $?
2

$ grep stuff /no/such/file
grep: /no/such/file: No such file or directory
$ test $? -eq 0 && echo ok || echo error $?
error 1

As was mentioned in an earlier reply, you can get round that by saving
the exit status in a variable, e.g.

$ grep stuff /no/such/file
grep: /no/such/file: No such file or directory
$ RET=$?
$ test $RET -eq 0 && echo ok || echo error $RET
error 2


-- 
Cheers,
Clive

[toc] | [prev] | [next] | [standalone]


#198932

From<tomas@tuxteam.de>
Date2018-08-17 15:40 +0200
Message-ID<wnN8S-J5-9@gated-at.bofh.it>
In reply to#198928
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 12:34:38PM +0100, Clive Standbridge wrote:

[...]

> > $ false
> > $ test $? && echo ok || echo error $?
> 
> The second $? in that line is different from the first; it's the exit
> status of "test". That can be demonstrated, with a corrected test
> command, by

No, because when the $? is expanded, the test hasn't run yet. This $?
*is* the (stringified) exit status of false, as can be seen in this
sequence:

  tomas@trotzki:~$ false
  tomas@trotzki:~$ test $? -eq 1 && echo "False"
  False
  tomas@trotzki:~$ true
  tomas@trotzki:~$ test $? -eq 1 && echo "False"
  tomas@trotzki:~$ 

> $ grep stuff /no/such/file
> grep: /no/such/file: No such file or directory
> $ echo $?
> 2

(as, BTW., *this* $? is not (yet) echo's exit status)

> $ grep stuff /no/such/file
> grep: /no/such/file: No such file or directory
> $ test $? -eq 0 && echo ok || echo error $?
> error 1

This one (eval goes left-to-right) should be the "test $? -eq 0"'s exit
status (it's not 0, so the && branch isn't taken).

> As was mentioned in an earlier reply, you can get round that by saving
> the exit status in a variable, e.g.

If you find yourself stashing too much in variables, you're holding
it wrong (sometimes you must, though).

> $ grep stuff /no/such/file
> grep: /no/such/file: No such file or directory
> $ RET=$?
> $ test $RET -eq 0 && echo ok || echo error $RET
> error 2

This is better spelt as

  grep stuff /no/such/file && echo ok || echo error $?

(or, se Greg's post downthread):

  if grep stuff /no/such/file ; then
    echo ok
  else
    echo error $?
  fi

Unless you need that exit status later in your script. Then,
stashing it in a variable may make sense.

Cheers
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt2zzMACgkQBcgs9XrR2kY2JACfeuDdw9kGedXQtlErfgzIspBp
3MYAn15g56XpCCfmr7yOgu5OJfcvPjM0
=IPFY
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#198929

FromGreg Wooledge <wooledg@eeg.ccf.org>
Date2018-08-17 14:30 +0200
Message-ID<wnM37-7a-13@gated-at.bofh.it>
In reply to#198921
On Fri, Aug 17, 2018 at 06:46:54PM +1000, Zenaan Harkness wrote:
> $ test $? && echo ok || echo error $?

Others have already pointed out that  test $?  is not what you think it
is.  When the test command is given 1 argument, it tests that argument's
string length.  If the string length is 0, then it's false.  If the
string length is non-zero, then it's true.

The string length of $? is always non-zero, so  test $?  is always true.

But what I really wanted to point out is that the  x && y || z  construct
is BROKEN and WRONG.  See <https://mywiki.wooledge.org/BashPitfalls#pf22>
for the verbose explanation.


On Fri, Aug 17, 2018 at 07:29:47PM +1000, Zenaan Harkness wrote:
> Is there a "cleaner" way to test the true/ error exit status other
> than using "$?", with bonus points for working in posix sh as well as
> Bash, ?

Simply use "if" like you're supposed to.

if mycommand arg1 arg2; then
  echo "it worked"
else
  echo "it failed"
fi

Or, if you only care about one of the two cases, you may use EITHER
the && or the || operator.  Just never, ever use both of them in the
same compound command.

mycommand arg1 arg2 || die "whoopsie"

[toc] | [prev] | [next] | [standalone]


#198935

From<tomas@tuxteam.de>
Date2018-08-17 15:50 +0200
Message-ID<wnNix-Mt-11@gated-at.bofh.it>
In reply to#198929
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 08:23:51AM -0400, Greg Wooledge wrote:
> On Fri, Aug 17, 2018 at 06:46:54PM +1000, Zenaan Harkness wrote:
> > $ test $? && echo ok || echo error $?
> 
> Others have already pointed out that  test $?  is not what you think it
> is.  When the test command is given 1 argument, it tests that argument's
> string length.  If the string length is 0, then it's false.  If the
> string length is non-zero, then it's true.
> 
> The string length of $? is always non-zero, so  test $?  is always true.

Exactly.

> But what I really wanted to point out is that the  x && y || z  construct
> is BROKEN and WRONG.  See <https://mywiki.wooledge.org/BashPitfalls#pf22>
> for the verbose explanation.

All generalizations suck :)

[...]

> Or, if you only care about one of the two cases, you may use EITHER
> the && or the || operator.  Just never, ever use both of them in the
> same compound command.
> 
> mycommand arg1 arg2 || die "whoopsie"

The construction

  foo && echo "bar" || echo "baz"

does probably work, because echo's exit status is (always?) 0 (the bash
builtin's documentation mumbles something about "write error"). And then,
the order matters -- first && then ||. I think such idiomatic constructions
are OK as long as you know what you're doing. As soon as the branches
contain more complex stuff, I agree you shouldn't do it: even if you've
convinced yourself that it works, the code becomes obscure and difficult
to understand/change by someone else (which might be yourself two years
down).

Cheers
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt20R4ACgkQBcgs9XrR2kY8CgCfYfHXfeDyqQ/ebWZrs24BPHIE
7NUAniyfZd2F/A/f27P1YVuuFP4nYnGi
=hE0n
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#198938

FromGreg Wooledge <wooledg@eeg.ccf.org>
Date2018-08-17 16:20 +0200
Message-ID<wnNLB-1bk-21@gated-at.bofh.it>
In reply to#198935
On Fri, Aug 17, 2018 at 03:43:58PM +0200, tomas@tuxteam.de wrote:
> The construction
> 
>   foo && echo "bar" || echo "baz"
> 
> does probably work, because echo's exit status is (always?) 0 (the bash
> builtin's documentation mumbles something about "write error").

echo can fail if stdout is closed, or if it's redirected to a file that
can't be written to (because of a full disk, etc.).

Sure, it may work 99.99% of the time, but it's still not safe.

[toc] | [prev] | [next] | [standalone]


#198940

From<tomas@tuxteam.de>
Date2018-08-17 16:40 +0200
Message-ID<wnO4W-1hq-15@gated-at.bofh.it>
In reply to#198938
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 10:12:54AM -0400, Greg Wooledge wrote:
> On Fri, Aug 17, 2018 at 03:43:58PM +0200, tomas@tuxteam.de wrote:
> > The construction
> > 
> >   foo && echo "bar" || echo "baz"
> > 
> > does probably work, because echo's exit status is (always?) 0 (the bash
> > builtin's documentation mumbles something about "write error").
> 
> echo can fail if stdout is closed, or if it's redirected to a file that
> can't be written to (because of a full disk, etc.).
> 
> Sure, it may work 99.99% of the time, but it's still not safe.

This particular idiom is still fine, since if stdout gets closed,
nobody will notice the difference between both branches anyway [1].

I still maintain that this pattern is OK, since it's idiomatic and
highly readable. But of course, you gotta know what you're doing,
and in which ways it may break down. And blog pages like yours are
invaluable in that (although we may disagree (methodically( somewhat
in this point, I am thankful that you go to the length of writing
out those things in a generally accessible manner).

Shell only looks simple at first sight. It's a nice "little language",
full of surprises and treasures. But it has to be treated with
respect :-)

Cheers

[1] https://en.wikipedia.org/wiki/If_a_tree_falls_in_a_forest
   somewhat (much) tongue-in-cheek :-P
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt23XsACgkQBcgs9XrR2kb7iQCeKCaitOt1MKnBXgRikIdA5LHR
BsoAn2i1Whwel4Qx4RIIm5bCBA0ItpI9
=oBeC
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#198965

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-18 01:10 +0200
Message-ID<wnW2t-69k-1@gated-at.bofh.it>
In reply to#198940
On Fri, Aug 17, 2018 at 04:36:43PM +0200, tomas@tuxteam.de wrote:
> On Fri, Aug 17, 2018 at 10:12:54AM -0400, Greg Wooledge wrote:
> > On Fri, Aug 17, 2018 at 03:43:58PM +0200, tomas@tuxteam.de wrote:
> > > The construction
> > > 
> > >   foo && echo "bar" || echo "baz"
> > > 
> > > does probably work, because echo's exit status is (always?) 0 (the bash
> > > builtin's documentation mumbles something about "write error").
> > 
> > echo can fail if stdout is closed, or if it's redirected to a file that
> > can't be written to (because of a full disk, etc.).
> > 
> > Sure, it may work 99.99% of the time, but it's still not safe.
> 
> This particular idiom is still fine, since if stdout gets closed,
> nobody will notice the difference between both branches anyway [1].
> 
> I still maintain that this pattern is OK, since it's idiomatic and
> highly readable. But of course, you gotta know what you're doing,
> and in which ways it may break down.

It's idiomatic for the C/Java programmer I guess, but now that I'm
beginning to understand the problem Greg points out (and now that I
remember, he posted that a few years ago, and I read it then too, and
now I'm even more grateful because it's so easy to miss the problem
of "mid pipe" failures being different to the "if then else" idiom.

The other part of my personal intention is to have my own code
(wherever it is), be maximally useful to newbies (been helping
someone with bash filename expansion and ? and * wildcards the last
few days) - so in this case, the subtleties are a trap for newcomers
- if they assume (which I had been up until the kind responses in
this thread) that "test && ||" is a reasonable replacement for "if
then else", that is quite likely to eventually cause problems - so I
want to be able to cut and paste my own scripts, and know that I'm
leading the target of my offer down a reasonable and reasonably safe
path, in cases beyond the immediate issue.


> And blog pages like yours are
> invaluable in that (although we may disagree (methodically( somewhat
> in this point, I am thankful that you go to the length of writing
> out those things in a generally accessible manner).

Folks taking the time to explain these things is such clarity is
indeed invaluable!


> Shell only looks simple at first sight.

‼


> It's a nice "little language",
> full of surprises and treasures. But it has to be treated with
> respect :-)

It might be little, but dang it's powerful. And Bash at least is not
really little (here I am, 20 years in, still struggling - although
that might say more about me than about Bash :)

Thank you everyone, really appreciated!
Zen



> Cheers
> 
> [1] https://en.wikipedia.org/wiki/If_a_tree_falls_in_a_forest
>    somewhat (much) tongue-in-cheek :-P
> -- t
> 

[toc] | [prev] | [next] | [standalone]


#198966

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-18 01:30 +0200
Message-ID<wnWlP-6f8-5@gated-at.bofh.it>
In reply to#198929
On Fri, Aug 17, 2018 at 08:23:51AM -0400, Greg Wooledge wrote:
> Simply use "if" like you're supposed to.

Sometimes the simple things in bash are free. Or something :)

Thank you so much Greg - I really appreciate this - this was the
answer I didn't know I wanted until you named it.

Kind regards,
Zen

[toc] | [prev] | [next] | [standalone]


#198920

From<tomas@tuxteam.de>
Date2018-08-17 11:30 +0200
Message-ID<wnJeV-6KG-5@gated-at.bofh.it>
In reply to#198913
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 06:46:54PM +1000, Zenaan Harkness wrote:
> 1)
> Bash man page largely fails to document the true and false builtins
> AFAICT, except for this sentence just under the heading
> "^SHELL BUILTIN COMMANDS":
> 
>  The :, true, false, and test builtins do not accept options and do
>  not treat -- specially.
> 
> But whilst the subsequent list of Bash builtin commands DOES include
> entries for ":" (the very first entry) and "test", it appears to fail
> to include entries for "true" and for "false".
> 
> This would not matter so much except for the following:
> 
> 
> 2)
> Why is executing "false" prior to testing it's output, apparently
> differen to executing "false" in a pipeline, e.g.:
> 
> $ false
> $ test $? && echo ok || echo error $?
> ok
> $ false blah
> $ test $? && echo ok || echo error $?
> ok

Note that after false, 

  test $? && echo ok || echo error $?

expands (after variable expansion) to

  test 0 && echo ok || echo error 0

... which ends up saying "ok", because test 0 succeeds :-)
The only one-arg test which fails is test "".
Yes, a bit unexpected, due to (a) the shell's evaluation model
and (b) test's behaviour.

To defend bash's documenters (a bit) its help system provides you
with tiny snippets of information (try "help false").

Cheers
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt2lKAACgkQBcgs9XrR2kYBJwCfePdOAVb3gxz9pcTqxWofLKNM
LcMAn2nZXDOwuhoxmbE+0wzEVX/oWceS
=7I3U
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#198922

FromZenaan Harkness <zenaan@freedbms.net>
Date2018-08-17 11:40 +0200
Message-ID<wnJoB-6ND-1@gated-at.bofh.it>
In reply to#198920
On Fri, Aug 17, 2018 at 11:25:52AM +0200, tomas@tuxteam.de wrote:
> On Fri, Aug 17, 2018 at 06:46:54PM +1000, Zenaan Harkness wrote:
> > 1)
> > Bash man page largely fails to document the true and false builtins
> > AFAICT, except for this sentence just under the heading
> > "^SHELL BUILTIN COMMANDS":
> > 
> >  The :, true, false, and test builtins do not accept options and do
> >  not treat -- specially.
> > 
> > But whilst the subsequent list of Bash builtin commands DOES include
> > entries for ":" (the very first entry) and "test", it appears to fail
> > to include entries for "true" and for "false".
> > 
> > This would not matter so much except for the following:
> > 
> > 
> > 2)
> > Why is executing "false" prior to testing it's output, apparently
> > differen to executing "false" in a pipeline, e.g.:
> > 
> > $ false
> > $ test $? && echo ok || echo error $?
> > ok
> > $ false blah
> > $ test $? && echo ok || echo error $?
> > ok
> 
> Note that after false, 
> 
>   test $? && echo ok || echo error $?
> 
> expands (after variable expansion) to
> 
>   test 0 && echo ok || echo error 0
> 
> ... which ends up saying "ok", because test 0 succeeds :-)
> The only one-arg test which fails is test "".
> Yes, a bit unexpected, due to (a) the shell's evaluation model
> and (b) test's behaviour.
> 
> To defend bash's documenters (a bit) its help system provides you
> with tiny snippets of information (try "help false").

$ help false
false: false
    Return an unsuccessful result.

    Exit Status:
    Always fails.


That accords with my previous understanding, that the exist status of
running false gives something other than "success" (i.e. zero) - what
am I missing?

[toc] | [prev] | [next] | [standalone]


#198924

From<tomas@tuxteam.de>
Date2018-08-17 11:50 +0200
Message-ID<wnJyh-6QO-13@gated-at.bofh.it>
In reply to#198922
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 07:32:39PM +1000, Zenaan Harkness wrote:

[...]

> That accords with my previous understanding, that the exist status of
> running false gives something other than "success" (i.e. zero) - what
> am I missing?

The next step: "$?" expands to "0" in your

  test $? && ...

then "test" sees "0" and thinks "ah, not null (i.e. ""), ergo true",
because the only one-argument call of 'test' which 'fails' would be
test "").

I think to really grok that you need to (re-)make yourself aware of
the shell's evaluation model: first, all the expansions (variable,
path, whatever), then what appears (after expansion) att command
position gets fed what appears in arg position.

Few surviving languages have that kind of evaluation model (the shells,
Tcl -- and in a very interesting twist the Lisps). Powerful, but
sometimes confusing.

Cheers
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt2mKAACgkQBcgs9XrR2kabGgCdGJt91a3/7a1O6/ugYqVhaQG+
CzcAnjy86+FXlIXJwUh4SU/OLUdLcBeh
=EXEw
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#198925

Fromtomas@tuxteam.de
Date2018-08-17 12:00 +0200
Message-ID<wnJHX-6TP-1@gated-at.bofh.it>
In reply to#198924
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, Aug 17, 2018 at 11:42:56AM +0200, tomas@tuxteam.de wrote:

[...]

> Few surviving languages have that kind of evaluation model (the shells,
> Tcl -- and in a very interesting twist the Lisps). Powerful, but
> sometimes confusing.

And (oh, sorry, how could have I forgotten that?) TeX, of course.

Cheers
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlt2m64ACgkQBcgs9XrR2kau4QCfTHLM8pn3v/EPDOL5RFoStHOc
8z4An1+qqtYCLq1N1gRguU/eBkiOFCjL
=6Ebr
-----END PGP SIGNATURE-----

[toc] | [prev] | [next] | [standalone]


#199276

FromStefan Krusche <linux@stefan-krusche.de>
Date2018-08-23 15:00 +0200
Message-ID<wpXnr-4bF-1@gated-at.bofh.it>
In reply to#198922
Am Freitag 17 August 2018 schrieb Zenaan Harkness:
> On Fri, Aug 17, 2018 at 11:25:52AM +0200, tomas@tuxteam.de wrote:
> > On Fri, Aug 17, 2018 at 06:46:54PM +1000, Zenaan Harkness wrote:
> > > 1)
> > > Bash man page largely fails to document the true and false builtins
> > > AFAICT, except for this sentence just under the heading
> > > "^SHELL BUILTIN COMMANDS":
> > >
> > >  The :, true, false, and test builtins do not accept options and do
> > >  not treat -- specially.
> > >
> > > But whilst the subsequent list of Bash builtin commands DOES include
> > > entries for ":" (the very first entry) and "test", it appears to fail
> > > to include entries for "true" and for "false".
> > >
> > > This would not matter so much except for the following:
> > >
> > >
> > > 2)
> > > Why is executing "false" prior to testing it's output, apparently
> > > differen to executing "false" in a pipeline, e.g.:
> > >
> > > $ false
> > > $ test $? && echo ok || echo error $?
> > > ok
> > > $ false blah
> > > $ test $? && echo ok || echo error $?
> > > ok
> >
> > Note that after false,
> >
> >   test $? && echo ok || echo error $?
> >
> > expands (after variable expansion) to
> >
> >   test 0 && echo ok || echo error 0
> >
> > ... which ends up saying "ok", because test 0 succeeds :-)
> > The only one-arg test which fails is test "".
> > Yes, a bit unexpected, due to (a) the shell's evaluation model
> > and (b) test's behaviour.
> >
> > To defend bash's documenters (a bit) its help system provides you
> > with tiny snippets of information (try "help false").
>
> $ help false
> false: false
>     Return an unsuccessful result.
>
>     Exit Status:
>     Always fails.
>
>
> That accords with my previous understanding, that the exist status of
> running false gives something other than "success" (i.e. zero) - what
> am I missing?

Nothing. What Tomás wrote is false (has exit code "1" ;-)

This:

  test $? && echo ok || echo error $?

does *not* expand as Tomás said to:

  test 0 && echo ok || echo error 0

but to:

  test 1 && echo ok || echo error 1

And "test 1" also succeeds, see Greg's message.

Kind regards,
Stefan

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.debian.user


csiph-web