The superficial answer is that it's always been that way, and so everybody does it. POSIX states that
If the file named by the file operand does not exist, cannot be read, or the type of the file named by the file operand cannot be determined, this shall not be considered an error that affects the exit status.
Unfortunately, no rationale is given, so the only obvious reason for why POSIX states that is historical practice.
The file
utility first appeared in Unix Research version 4 in 1973. At the time, standard utilities didn't check for errors (even though processes had had a return status since at least version 3 if not version 2). For example, cat
started returning a nonzero status if a file did not exist only in version 8: version 7 just printed an error message and kept going. But even by version 10, file
only exited with a nonzero status if it could not read the magic
file, not if it could not read a data file.
A possible reason for file
not to fail is that it isn't just interested in file contents, but also in files types, and it considers “does not exist” to be a special kind of file alongside directory, symbolic link, broken symbolic link, etc. This is a weak justification since an unreadable file is really not a special kind of file, it's a file whose nature cannot be determined, which is an error by any sensible measure. Also, it could apply to ls
, which still did not return an error if given a nonexistent file name as of version 10, but for which this eventually became universal practice.
So it seems that the return status of file
is a mistake that time forgot. Now that there are probably scripts out there that rely on file
not returning an error status if the file does not exist, it's too late to change.