-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 test currently treats -a, -o, and -N as undocumented unary ops in test_unop(), but in unary_operator(), -a maps to -e, but -o and -N are ignored as invalid. This leads to some strange behavior:
$ /bin/test -e ChangeLog ; echo $? 0 $ /bin/test -q ChangeLog ; echo $? /bin/test: -q: unary operator expected 2 $ /bin/test -a ChangeLog ; echo $? 0 $ /bin/test -o ChangeLog ; echo $? /bin/test: extra argument `-o'2 $ /bin/test -N ChangeLog ; echo $? /bin/test: extra argument `-N'2 $ /bin/test a ChangeLog ; echo $? /bin/test: missing argument after `ChangeLog'2 First, the 'extra argument' and 'missing argument' error messages are missing a trailing newline. Second, it is confusing that -a is silently accepted, but that non-unary operators that look like an operator, such as -q, get a different error message than non-unary operators that are completely random, which are yet different from the special cases of -o and -N. I think -a was added to match bash's unary -a as a synonym for -e, and -N intends to match bash's - -N which returns true if a file has been modified since it was last read; bash's unary -o is unimplementable in /bin/test since there is no way to determine if a shell option is set when test is not a shell builtin. However, none of these behaviors violate POSIX, since test is allowed to produce unspecified results when there are 2 arguments, the first is not '!', and the first is not a unary primary. The POSIX violation comes in when you now try to negate these tests: $ /bin/test ! -a ChangeLog ; echo $? 1 $ /bin/test ! -o ChangeLog ; echo $? /bin/test: extra argument `-o'2 $ /bin/test ! = ! ; echo $? 0 My reading of POSIX is that when there are three arguments, binary operators take precedence over ! (although this is probably worth an aardvark, since when there are more than 3 arguments, there is no explicit requirement of precedence between ! vs. binary -a). Note that "/bin/test ! = !" correctly parsed the same as "/bin/test x! = x!", by recognizing that = is a binary operator. I argue that "/bin/test ! -a ChangeLog" should also parse as "/bin/test \( ! \) -a ChangeLog", which performs a 1-argument test on both ! and ChangeLog (both are non-empty), and results in true (exit status 0); rather than parsing as "/bin/test ! \( -a ChangeLog \)", performing the unary -a, then negating it, resulting in false (exit status 1). Likewise, "/bin/test ! -o ChangeLog" should perform two 1-argument tests, and return true, since binary -o should have higher precendence than a negation of a (non-existant) unary -o. - -- Life is short - so eat dessert first! Eric Blake [EMAIL PROTECTED] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFDwm9z84KuGfSFAYARAre4AJ0eo4/IsTqvpOH/kQEruark3MoUCQCeMtEV JBkrzBLcSWKu4MZBN4cSW/I= =repS -----END PGP SIGNATURE----- _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils