Bug: true and false are not Posix (2016)
lists.gnu.org
lists.gnu.org
Nobody is calling true or false in a script with options/arguments. Nobody hss ever seen true/false fail because they crashed in setlocale. Nobody's highest, second-highest, or 1000th-highest risk to their code is the performance of their true/false implementation.
But it's a really easy thing to have opinions about. You use UNIX for one week and suddenly you're exactly as qualified as Dennis Ritchie to have opinions on the matter.
if [ -x /usr/bin/blah ]
then
BLAH=/usr/bin/blah
else
BLAH=/bin/true
fi
$BLAH foo bar baz
They wanted BLAH to be a noop if blah didn't exist. I could only think of /bin/true as a noop at the time, but I needed it to ignore parameters.The man page defines that it does.
(in retrospect, we could have defined an sh function noop {} )
* https://unix.stackexchange.com/a/497561/5132
The conditionally defined shell function in one of the other answers is a more appealing approach, especially given the native behaviours of some shells with respect to variable expansion. But also given that /bin/true is not necessarily the pathname.
% export BLAH='/bin/true too'
% dash -c '$BLAH 1 2 3'
% dash: 1: /bin/true: not found
% sh -c '$BLAH 1 2 3'
/bin/true: not found
% ksh -c '$BLAH 1 2 3'
ksh: /bin/true: not found
% zsh -c '$BLAH 1 2 3'
zsh:1: no such file or directory: /bin/true too
% bash -c '$BLAH 1 2 3'
bash: /bin/true: No such file or directory
%
% export BLAH='/usr/bin/true too'
% zsh -c '$BLAH 1 2 3'
zsh:1: no such file or directory: /usr/bin/true too
% bash -c '$BLAH 1 2 3'
% ksh -c '$BLAH 1 2 3'
% dash -c '$BLAH 1 2 3'
%I wrote that answer because I recalled it as a common idiom in autoconf or something -- some automake system I'd seen where the system seeks out the tools it needs and defines them as variables.
"The system may provide non-standard extensions. These are features not required by POSIX.1-2017 and may include, but are not limited to:
Additional functions
[ ... ]
Additional options for standard utilities"
[ ... ]"
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_...
A standard utility that takes no options can be extended locally to take options. "Some options" constitutes "additional options" relative to "no options".
Since the descriptions of true and false say they take no options; therefore POSIX-conforming scripts don't pass any. A POSIX-conforming script has no way of finding out whether true or false take implementation-defined options (i.e. any options whatsoever).
Whether it’s “not common sense” is not very apparent when “common sense” is pretty difficult to define here (as often the case).
Ok, so undefined behavior is seen an escape valve through which the devs can change longstanding behavior in the interest of consistency with a newer set of interface standards they've devised. Fine.
But then this response from a dev on that mailinglist[1]:
> Note that it is a high bar to change the behavior of something like 'true'.
Hm... now I'm slightly intrigued.
Did the change that introduced the standard "--help" flag and addition of locale-related code flow directly from the "escape valve" of undefined behavior in POSIX? Or was the undefined behavior merely a starting point for a much more involved discussion about whether to change a long-standing interface that could introduce subtle bugs in old scripts/programs that relied on implementation details of undefined behavior?
Edit: clarification. Also if someone can point me to a mailing list discussion that shows evidence of the latter I would be much obliged.
[1] https://lists.gnu.org/archive/html/bug-coreutils/2016-03/msg...
Changing thr behaviour is a braking change because they are no longer conforming to their old spec. Adding the flag is not a breaking change, as they stayed consistent with the old spec
Was there a time when GNU existed without the "--help" flag? Or was it originally committed with the "--help" flag present?
Shells are pretty much the wild west out there. I wouldn't be too surprised if some AIX shell variant or something came along and consistently bails out with an error when any argument is given to 'true', including --version. It might not be a common shell variant for you, but it might for other people. Hence, standards.
I'm not really arguing in favor of --help and --version to 'true'. I just don't see much of a problem with it.
The worst may be the System V version, which added a copyright notice.
Oh come now. I'm quite sure my hello world program is bug free. It prints "Hello World" successfully, and there are zero other cases that could exist.
https://www.gnu.org/ghm/2011/paris/slides/jim-meyering-goodb...
Since then, it has infinitely bloated on most systems.
It actually began at AT&T, where they apparently decided to copyright the trueness. From there it went downhill, ever and ever.
/proc/bin/true
/proc/bin/false
The exec doesn't even need to create page tables or run any non-kernel code. This is a benchmark-winning design.
Of course "spawning a shell" can be very cheap, as you are already in a shell, it's just fork() plus some initialization code (compared to fork() plus exec() for running a non-shell program)
Note that shells must try to interpret at least any text file for which the system returns ENOEXEC [1]
1: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3... Read subsection 1.e.i.b
Files:
1.sh:
true
2.sh: #!/bin/bash
true
test1.sh: for i in `seq 10000`
do
./1.sh
done
test2.sh: for i in `seq 10000`
do
./2.sh
done
Times for test1.sh: 11.484s
11.590s
11.405s
Times for test2.sh: 14.273s
14.391s
13.847s
So including the #! adds about 23% to the overhead of calling a shell script. Tested on Mint 19.1, bash.EDIT: for reference, sourcing the scripts instead takes an average of 0.0842s for test1 and 0897s for test2. (and all test2 trials were still slower than all test1 trials), which isn't particuarly suprising.
Inlining true takes about 0.029s
Besides, /bin/sh would also require dereferencing a symlink (to /bin/dash), which also doesn't seem fair.