Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -
DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' -
DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -
DSHELL -DHAVE_CONFIG_H -I. -I../bash -I../bash/include -I../bash/
lib -g -O2 -Wall
uname output: Linux virtsrv2 2.6.28-13-server #44-Ubuntu SMP Tue Jun 2
08:40:28 UTC 2009 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu
Bash Version: 3.2
Patch Level: 48
Release Status: release
Description:
Use of the '-a' option to the builtin test command fails to
produce the correct result when used with negation. The specific
error the case where the file exists and a "test ! -a file" is
executed. If the script is changed to use '-e' for file
existence the result is correct as expected. If the script is
modified to place parenthesis around the '-a file' expression,
the result is also correct.
Repeat-By:
Run the following bash script to see all behaviors including the
behavior of the /usr/bin/test command:
---------------cut------------
#!/bin/bash
#
fn=._you_better_not_have_this_file
trap "rm -f $fn" 0
for (( tc=0; tc < 4; tc++ ))
do
echo "Starting case $tc"
case $tc in
"0") # bash test builtin; bracket operator
ts=\[
te=\]
to=-a
;;
"1") # bash test builtin; test
ts=test
te=
to=-a
;;
"2") # system standalone test
ts=/usr/bin/test
te=
to=-a
;;
"3") # bash test builtin; test; -e unary op
ts=test
te=
to=-e
;;
esac
#
if eval $ts $to $fn $te
then
echo "surprised (not good)"
fi
if eval $ts ! $to $fn $te
then
echo "file $fn not present (good)"
fi
touch $fn
if eval $ts $to $fn $te
then
echo "file present (good)"
fi
if eval $ts ! $to $fn $te
then
echo "file $fn not present (bug)"
fi
echo "Completed case $tc"
echo
rm -f $fn
done
---------------cut------------
Fix:
Changing the order of clauses in the three_arguments function to
look for negation before the possibility of an and/or expression
solved the problem for me. It also passed the test cases for the
test operator. This is consistent with the way things are handled
in the coreutils standalone test program.
--- bash-3.2-dist/test.c 2006-01-29 11:44:02.000000000 -0800
+++ bash-3.2/test.c 2009-07-20 19:20:08.000000000 -0700
@@ -709,14 +709,6 @@ three_arguments ()
value = binary_operator ();
pos = argc;
}
- else if (ANDOR (argv[pos+1]))
- {
- if (argv[pos+1][1] == 'a')
- value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]);
- else
- value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]);
- pos = argc;
- }
else if (argv[pos][0] == '!' && argv[pos][1] == '\0')
{
advance (1);
@@ -727,6 +719,14 @@ three_arguments ()
value = ONE_ARG_TEST(argv[pos+1]);
pos = argc;
}
+ else if (ANDOR (argv[pos+1]))
+ {
+ if (argv[pos+1][1] == 'a')
+ value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]);
+ else
+ value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]);
+ pos = argc;
+ }
else
test_syntax_error (_("%s: binary operator expected"), argv[pos
+1]);
---EOF---