bash, with context of two arguments
-a file and
-e file are the same. But they have some difference, because
-a is also a binary operator.
-e unary is defined by POSIX, but
-a unary isn't. POSIX only defines
-a binary (See test POSIX).
POSIX defines three arguments
If $2 is a binary primary, perform the binary test of $1
If $1 is '!', negate the two-argument test of $2 and $3.
If $1 is '(' and $3 is ')', perform the unary
test of $2. On systems that do not support the XSI option, the results are unspecified if $1 is '(' and $3 is ')'.
Otherwise, produce unspecified results.
-a also leads to strange result:
$ [ ! -a . ] && echo true
-a is considered as binary operator in context of three arguments. See Bash FAQ question E1.
POSIX also mentions that
-a is get from KornShell but was changed later to
-e because it makes confusing between
-a binary and
The -e primary, possessing similar functionality to that provided by
the C shell, was added because it provides the only way for a shell
script to find out if a file exists without trying to open the file.
Since implementations are allowed to add additional file types, a
portable script cannot use:
test -b foo -o -c foo -o -d foo -o -f foo -o -p foo
to find out if foo is an existing file. On historical BSD systems, the
existence of a file could be determined by:
test -f foo -o -d foo
but there was no easy way to determine that an existing file was a
regular file. An early proposal used the KornShell -a primary (with
the same meaning), but this was changed to -e because there were
concerns about the high probability of humans confusing the -a primary
with the -a binary operator.
-a binary is also marked as obsolescent, because it leads to some ambiguous expression, which has greater than 4 arguments. With these >4 arguments expression, POSIX defines the result is unspecified.