Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29233 Discussions

Detecting file/directory existence

Dishaw__Jim
Beginner
2,296 Views
From my understanding, there is not a standard method for determining if a file or directory exists. Using IVF compiler there are a choice of three methods:
  • GETFILEINFOQQ
  • STAT
  • INQUIRE
GETFILEINFOQQ requires an iteration until "handle" equals FILE$LAST or FILE$ERROR, otherwise a memory leak may occur. This method appears to work consistently on all of the IVF supported platforms.

STAT looks like the best choice, however, the documentation has the following

On Windows systems, the result is zero if the inquiry was successful; otherwise the error code ENOENT (the specified file could not be found). On Linux and Mac OS systems, the file inquired about must be currently connected to a logical unit and must already exist when STAT is called; if STAT fails, errno is et.
So, it would appear, that using STAT() on Linux/MacOS to determine if a file or directory exists will not work the same. Also, how can a directory be connected to a logical unit? I'm guessing that STAT() on Linux and MacOS only works with files that have been OPENed.

INQUIRE has been extended to use the DIRECTORY= parameter. According to the documentation, IVF can INQUIRE files that have not been OPENed when used with the FILE= parameter. It appears that not all Fortran compilers support this behaviour. Does the Fortran specification provide any guidance?

It would appear that the hierarchy of choices are:

  • If you need to support wildcards, GETFILEINFOQQ is your only choice.
  • If you need to support files or directories without distinguishing between them then STAT() is the better choice, at least on the Windows platform. The documentation is not clear how it will work on Linux and MacOS.
  • If you need to determine if a file exists, then INQUIRE seems to be the most portable method.
  • For directories, INQUIRE seems like a good choice and it avoids using the Portability routines (IFPORT).
  • The only portable method for determining if a file exists is to attempt to open it and to determine if it succeeds. The downside to this approach is the overhead associated with opening a file
Is that a fair assessment of the options?

0 Kudos
5 Replies
Steven_L_Intel1
Employee
2,296 Views

Not all of your assessment is correct.

First, the Fortran standard makes no mention of "directories" - it does not have the concept. It DOES have the concept of INQUIRE(FILE=) allowing you to ask questions about a file which may or may not be currently be opened by Fortran in the program. So your last bullet is incorrect.

The part of this which gets confusing is when you try to extend the concept of file to "directory". The standard says, in the description of NAME=, "the value returned shall be suitable for use as the value of file-name-expr in the FILE= specifier in an OPEN statement." In other words, if INQUIRE admits that it knows about a file, it is something you ought to be able to OPEN (at least in some circumstances)

On some operating systems, you can open a directory as if it were a file, on others you can't. We decided that there were enough restrictions on directories that it made sense to separate them from files and add new keywords as extensions.

So, there is no Fortran standard way to ask if a directory exists.(Ignoring for now that even the syntax for directories is non-portable.) The closest you can come is the POSIX routine PXFOPENDIR which opens a directory. For compilers that support the POSIX Fortran library, this should be reasonably portable.

0 Kudos
Dishaw__Jim
Beginner
2,296 Views
Thanks for your quick reply.

My goal is not to open a directory, rather it is to (a) give a meaningful error message or (b) create the directory. Because dealing with directories is non-portable, I use ifdef blocks to get the correct (or reasonable) behaviour on different platforms.

My point about INQUIRE(DIRECTORY=dir) is that it appears to have consistent behaviour (per the documentation) for all platforms supported by IVF. STAT() does not seem to work the same on the different platforms--the documentation says for Linux/MacOS "the file inquired about must be currently connected to a logical unit and must already exist." I don't know what "currently connected to a logical unit" means for a directory. The documentation seems to imply that if you do a STAT() on a file that has not been OPENed then it will return an error.

Based on your response, INQUIRE(FILE=) will tell you if a file exists independently of whether is has been OPENed. Is that behaviour specified in the Fortran standard or is it subject to the implementation of the compiler vendor?

0 Kudos
Steven_L_Intel1
Employee
2,296 Views

"connected to a unit" means opened.

The standard does allow FILE= on a file that has not been opened. You can safely depend on that across all implementations.

I suggested PXFOPENDIR not because you wanted to open the directory, but because it was a "portable" way of detecting if a directory existed. You would close it immediately afterward.

If you're always using Intel Fortran, you can use the INQUIRE extension for directories.

0 Kudos
grg99
Beginner
2,296 Views
One bit of a Kludgy way to detect a directory is to do an OPEN( STATUS='NEW') to attempt to create a file in the puported directory. If that fails then either the directory doesnt exist, or isnt writeble, which is also nice to know.


0 Kudos
jimdempseyatthecove
Honored Contributor III
2,296 Views

It is not acceptible to modifythe file system for the purpose of determining the presense of a directory: "Do no harm"

I haven't tried this on all platforms as I only have a Windows

1) Use GETDRIVEDIRQQ to obtain, and save, the current directory on the drive of interest. (Note, the current directory can potentially be invalid)

2) Use CHANGEDIRQQ to attempt to sellect the directory in question, save the return logical indicator.

3) Use CHANGEDIRQQ to attempt to reset the old current directory (assuming you obtained a valid current directory in 1) above)

Jim Dempsey

0 Kudos
Reply