I was looking up the meaning of flags like -a
in zsh if
statements, eg.
if [[ -a file.txt ]]; do
# do something
fi
and I found this
-a file
true if file exists.
-e file
true if file exists.
What is the difference between -a
and -e
? And if there is none, why do they both exist?
POSIX sheds some light on this.
tl;dr: Ksh traditionally used -a
and several other shells followed suit. POSIX instead borrowed -e
from Csh to avoid confusion. Now many shells support both.
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.