In bash
, with context of two arguments test
command, -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 test
behaviour:
3 arguments:
If $2 is a binary primary, perform the binary test of $1
and $3.
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.
So -a
also leads to strange result:
$ [ ! -a . ] && echo true
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 -a
unary.
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.
Best Answer
There is no difference whatsoever. The POSIX description of both options reads
As you say, the reason to have both is most likely to support the most common choices made by historical implementations of the
test
and[
utilities.As for the
test
and[
built-in utilities ofbash
, they both functions the same, and have always done. The oldest availablebash
source in the current Git repository has the same wording for both (release 2.04, from 1991).In the actual 1991 implementation, there's even a comment: