Checking To See If A File Exists

No matter what programming language you are using, all multiple-access file systems have the problem that the system may correctly report that a file does exist, and then when you attempt to use it you may find that it does not, because someone has deleted or renamed it in the meantime.

The operations below can help you avoid problems, but in the final analysis, the only way to tell whether you can open a file is to try to open it.


file_exists(+FileName)
FileName must be an atom. file_exists/1 succeeds if a file of that name exists. If there is something of that name, but it is a directory, file_exists/1 fails. You need sufficient rights to the file to be able to determine whether it is a directory (see stat(2)). Named pipes and devices are accepted as files.
file_exists(+FileName, +Permissions)
FileName must be an atom, and Permissions must be one of the following, or a list of them:

exists
does the file exist?
read
can the file be read?
write
can the file be over-written?
N
N is an integer(N); see access(2)

file_exists/2 succeeds when there is a file (not a directory) named FileName and you have each of the Permissions you named.

If Permission is an integer, it is interpreted the way that the argument to the system call access(2) is interpreted, namely (the file must exist)

              + 1 * ('execute' permission is wanted)
              + 2 * ('write' permission is wanted)
              + 4 * ('read' permission is wanted)>
          

This is allowed so that a C programmer who is used to writing

          if (!access(FileName, 6)) {
              can_read_and_write(FileName);
          } else {
              cannot_access_file(FileName);
          }
          

can write

          (   file_exists(FileName, 6) ->
              can_read_and_write(FileName)
          ;    /* otherwise */
              cannot_access_file(FileName)
          )
          

We recommend, however, that you code this example as

          (   file_exists(FileName, [read,write]) ->
              can_read_and_write(FileName)
          ;       /* otherwise */
              cannot_access_file(FileName)
          )
          

Under operating systems that do not support version numbers (as UNIX and Windows do not), file_exists/2 could fail (because there is no such FileName) and can_open_file/2 could succeed (because you are allowed to create one). Conversely, file_exists/2 could succeed (because there is such a FileName) and can_open_file/2 fail (because you have so many files open that you cannot open another).

file_must_exist(+FileName)
succeeds when file_exists(FileName) succeeds; otherwise, it raises an error exception.
          | ?- file_must_exist(fred).
          ! Existence error in file_must_exist/1
          ! file fred does not exist
          ! O/S error : No such file or directory
          ! goal:  file_must_exist(fred)
          

file_must_exist(+FileName, +Permission)
succeeds when file_exists(FileName, Permission) succeeds; otherwise, it raises an error exception.
          | ?- unix(system('ls -l files.o')),
               file_must_exist('files.o', write).
          
          -r--r--r--  1 ok       746 Jan 24 17:58 files.o
          ! Permission error: cannot access file 'foo.o'
          ! O/S error : Permission denied
          ! goal:  file_must_exist('foo.o',write)
          

can_open_file(+FileName, +Mode, +Quiet)
FileName is a filename. Mode is read, write, or append, just as for the open/3 command. can_open_file/2 fails quietly if the file cannot be opened. The Quiet parameter controls the raising of an error exception when the file cannot be opened: if Quiet is fail, can_open_file/3 fails quietly, whereas if Quiet is warn, it raises an error exception. If Mode is

read
FileName must exist and be readable
append
FileName must exist and you must have permission to append to it, or FileName must be nonexistent in a directory in which you have permission to create a new file
write
the same conditions apply as for append

This predicate actually attempts to open the file. It will, for example, create a file in order to determine whether it can create it. But if that happens, it immediately deletes the file again, so there should be no permanent effect on the file system.

can_open_file(+FileName, +Mode)
equivalent to can_open_file(FileName, Mode, fail).
open_file(+FileName, +Mode, -Stream)
is the same as the built-in predicate open/3 (which is described in the reference pages), except that it always raises an error exception if it cannot open the file, and is not sensitive to the fileerrors flag.
current_dec10_stream(?FileName, ?See_or_Tell)
is true when See_or_Tell is see and FileName is a file that was opened by see(FileName) and has not yet been closed, or when See_or_Tell is tell and FileName is a file that was opened by tell(FileName) and has not yet been closed. It is a version of current_stream/3, which just tells you about the Dec-10-compatible streams. It relies on two facts: (1) all the streams you opened are in the current_stream/3 table. (2) seeing/1 (telling/1) return an atom if and only if the current input (output) stream was opened by see/1 (tell/1), and the atom it returns is the one given to see/1 (tell/1).
close_all_streams
closes all the current streams except the standard streams.

None of the predicates described in this section is affected by the fileerrors flag. Indeed, they exist so that you can check for errors before they happen.

See the summary description of library(ask) (lib-uin) for two useful predicates that use can_open_file/3.