Though I have not tested for the stable version, I am afraid this bug still exists in the latest version because I cannot find any related bug on the BTS. Not only Debian (oldstable) but the latest Suse has the same problem, and I am afraid this is a very widely-spread unfixed bug... Please try % bash -c 'test ! -a . && echo true' and compare with the result of % bash -c '/usr/bin/test ! -a . && echo true' . The '[' builtin has the same problem, as expected. What is interesting is that the results of % bash -c 'test ! -z foo && echo true' and % bash -c '/usr/bin/test ! -z foo && echo true' agree to each other. Regards, Masanobu Ozaki
tags 426990 + moreinfo found 426990 bash/4.1-3 quit Hi Masanobu, OZAKI Masanobu wrote: So which one is right? My first reading was: test ! -a . = test ! && test . = test -n ! && test -n . = true && true = true though I expect you were looking for: test ! -a . = ! test -a . = ! test -e . = ! true = false Right, this one is not ambiguous. My recommendation is to never use the ! or -a 'test' operators. They are superfluous next to the shell-supported ! and &&. POSIX does not mandate support for -a (though XSI does), perhaps for this reason. Hope that helps, Jonathan
Hi Jonathan, sometimes returns the correct result, but have not found what makes the difference. Plus, this problem might have been fixed in current stable (Version: 3.2-4) package: I cannot represent the problem now. According to the help command, the '-a FILE' file operator returns true if file exists. I found this problem when debugging a code written by my colleague. Thanks, Masanobu
tags 426990 - moreinfo
tags 426990 + upstream
# documentation bug
severity 426990 minor
retitle 426990 bash: "help test" gives no hint of complicated precedence rules
quit
OZAKI Masanobu wrote:
Summarizing: There are two -a operators: a unary one and a binary one.
This results in reduce/reduce conflicts when parsing a "test" expression.
"help test" says:
See the bash manual page bash(1) for the handling of
parameters (i.e., missing parameters).
which does not really tempt me to look at the manual. bash(1) says:
Expressions may be combined using the following
operators, listed in decreasing order of precedence.
giving an order of precedence with ! before -a. Then it quickly
corrects itself:
test and [ evaluate conditional expressions using a set
of rules based on the number of arguments.
0 arguments
The expression is false.
[...]
3 arguments
If the second argument is one of the
binary conditional operators listed above
under CONDITIONAL EXPRESSIONS, the result
of the expression is the result of the
binary test using the first and third
arguments as operands. The -a and -o
operators are considered binary operators
when there are three arguments.
That answers the question. Unfortunately, the next sentence is
inconsistent with that answer:
If the first
argument is !, the value is the negation of
the two-argument test using the second and
third arguments.
Suggested changes:
1. Change the parenthesis in "help bash" to something like
"(e.g., operator precedence and missing parameters)".
2. Change the second paragraph in the description in bash(1) of
the test builtin to something like
Expressions may be combined using the following operators.
The evaluation depends on the number of arguments; see below.
When 5 or more arguments are present, this list is in
decreasing order of precedence.
3. Add the word "Otherwise," before "If the first argument is !" in
the 3-argument case.
Thoughts? I can try writing a patch if this looks like a good idea.
imadev:~$ bash -c 'test ! -a . && echo true' true imadev:~$ bash -c '/usr/bin/test ! -a . && echo true' imadev:~$ This is an extremely convoluted example. You're echoing true if the object does NOT exist...? Actually, you're echoing true if the command fails to fail. In the /usr/bin/test -a case, the command has the right to fail because there's no such unary operator (see below), regardless of whether . exists in the file system. (On my system, there is no -a unary operator in the test(1) man page, but the command apparently supports one, undocumented. Isn't this fun?) http://www.opengroup.org/onlinepubs/9699919799/utilities/test.html for details. It specifies -a as a binary operator, but marks it as obsolescent and suggests using two test commands instead. This is the same advice I give whenever the subject comes up on IRC, and also what I mention on my pitfalls page: http://mywiki.wooledge.org/BashPitfalls#pf6 [...] I'll let Chet address those. Speaking strictly as someone who supports script writers (not shell maintainers), I'd suggest either using bash's [[ command instead of test, or avoiding the use of -a and -o in the test command. (Note that [[ uses && rather than -a, and || rather than -o. So whichever advice path you choose, -a and -o as binary operators are just plain bad.) If you're trying to determine whether some file-object exists, use -e. imadev:~$ bash -c 'test ! -e . && echo true' imadev:~$ bash -c '/usr/bin/test ! -e . && echo true' imadev:~$ If you're trying to run multiple tests, use multiple test commands, and string them together with && and/or || as required. imadev:~$ bash -c 'if test -e . && test -e ..; then echo true; fi' true imadev:~$ bash -c 'if /usr/bin/test -e . && /usr/bin/test -e ..; then echo true; fi' true Or use [[: imadev:~$ bash -c 'if [[ -e . && -e .. ]]; then echo true; fi' true
You should probably ask the person who added that to Debian's version of bash. The phrase you're quoting appears in both the description of the [[ conditional command and the test/[ builtin. If you're quoting the latter, why omit the next sentence, which reads: The evaluation depends on the number of arguments; see below. Again, talk to the Debian maintainer who added it. Something like that is reasonable. The sentences are supposed to indicate precedence. It would actually be clearer if they were separated into bullet points, as they are in the Posix standard. I'll look at doing that. Chet
Hello. On Mon, 2010-11-08 at 08:45:11 -0500, Greg Wooledge <wooledg@eeg.ccf.org> wrote: "both should echo true" in previous email, but that is wrong. Both should echo nothing, as you expect. I am sorry for my confusing message. Neither on my system. I found descriptions of the -a unary operator in the output of "help test" output and ksh(1) man page. According to Solaris 7's test(1) page (http://docs.sun.com/app/docs/doc/805-3172/6j31br5p3?l=en&a=view), which summarizes variations of test command, I guess this is ksh origin and influenced (or polluted?:) /bin/test and bash. I found the inconsistency between bash-builtin and GNU shell util's test commands when porting a ksh script to bash in order to avoid a ksh's bug that randomly occurred on Scientific Linux. Regards, Masanobu
It's difficult to figure out who first introduced an extension. Most of these things predate POSIX, and were extensions to either SVID or BSD standards. POSIX had the unenviable job of deciding which features were common enough to mark as "standard" and which were not. On a different note, that man page is rather dodgy. It says /usr/bin/test [condition] and then if condition ; then action ; fi Are they saying that Solaris's sh would accept this? if -d /etc; then echo "good, you have /etc"; fi That's what it LOOKS like it's saying, but surely that can't be right.... "It's easier to port a shell than a shell script." -- Larry Wall