Search code examples
zsh

What's the difference between -a and -e in a zsh conditional expression?


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?


Solution

  • 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.