Silverfrost Forums

Welcome to our forums

Testing for a directory

3 Aug 2011 8:37 #8698

The code below works well when testing for a valid directory using gfortran (on Linux). Trying the same code using FTN95 the inquire does not work to test for a directory.

Question: Does inquire only works for files? Which other possibilties exist to test for a valid directory using standard Fortran.

program directory
    implicit none
    character(len=256) :: dir,sys_cmd
    logical :: test_for_dir

    dir = 'C:\\temp\\test_dir'
    inquire(file=dir,exist=test_for_dir)
    if (.not.test_for_dir) then
        sys_cmd = 'mkdir '//TRIM(dir)
        write(*,*) TRIM(sys_cmd)
        call SYSTEM(sys_cmd)
    else
        write(*,*) 'Save files in '//TRIM(dir)
    endif

end program directory
3 Aug 2011 9:46 #8701

I may be wrong but I thought that 'CALL SYSTEM' was not standard fortran, with Silverfrost you can use either 'CALL CISSUE@' or the function START_PROCESS@ both of which are also non-standard.

3 Aug 2011 9:55 #8702

The SYSTEM call is not to be found in the FTN95 documentation. However, it works, i.e. the directory is created - http://imageshack.us/photo/my-images/508/directory.jpg/

If the directory exists the inquire command does not work. Instead I should try to write to the directory. Then agian, the code works fine with gfortran.

3 Aug 2011 10:16 #8703

But isn't INQUIRE only supposed to be used for a unit number or a file? The FTN95 help makes no mention of using INQUIRE with directories and a brief search of the web only agreed with the FTN95 usage. I may be wrong again but it seems to me that gfortran might be using an extension to the standard in permitting directories to be inquired.

3 Aug 2011 10:44 #8704

I suppose that using a unit number is the correct way. This at least confirm what my understanding of inquire is.

I think the best solution would be to implement the directory test in some other way! The test is only performed at the beginning of the program, i.e. the effort would be manageable.

3 Aug 2011 11:14 #8706

May be this helps?

WINAPP 
OPTIONS(INTL) 

PROGRAM TEST 

IMPLICIT NONE 
INCLUDE <WINDOWS.INS> 

integer*2      dummy
character*200  pfad

pfad = 'c:\\blabla\'
call attach@(pfad,dummy)
if (dummy .ne. 0) then
  print*,'path did not exist'
  call mkdir@(pfad,dummy)
  if (dummy .eq. 0) print*,'path created'
else
  print*,'path exists!'
end if
end

Regards - Wilfried

3 Aug 2011 12:51 #8713

Wilfried, a clever solution. This whole post is complemented by the discussion over FEXISTS@ in this forum just a few threads back.

Eddie

3 Aug 2011 1:15 #8714

Thanks for the example and the tipp!

Both solutions make use of FTN95 non-standard solutions. And the aim is to avoid this. I found several entries where the inquire function works for testing directories as well (link):

(https://groups.google.com/group/comp.lang.fortran/msg/c688c4a58bdcce5d?hl=en)):[quote:611d8eb2cf]> > > > > INQUIRE(FILE='some directory specification',EXIST=ex) correctly tests

for the existence of a directory with all my Windows compilers (g95,gfortran,lf95) except IVF. Does anybody know the reason for this and what the standard says if anything?

This topic is also discussed in other Fortran forums and it seems like the Fortran standard does not provide anything in this regard. However, according to http://rosettacode.org/wiki/Ensure_that_a_file_exists#Fortran it shoul be possible.

3 Aug 2011 1:39 #8715

None of the links below after searching for the Fortran standard for the INQUIRE statement mentions using it for directories.

So I don't think it is a failing of Silverfrost FTN95

Wilfried's solution is neat, but of course you end up with different code for gfortran and ftn95, but there again you can only expect standard code to be truly portable between compilers and platforms.

Fortran 77 stndard here:-

http://www.fortran.com/F77_std/rjcnf-12.html#sh-12.10.3

Fortran 95 handbook: complete ISO/ANSI reference

http://books.google.co.uk/books?id=AUx7vKIiuvwC&pg=PA352&lpg=PA352&dq=fortran+95+inquire+standard&source=bl&ots=ONrHPnOU3o&sig=io77qkKZVyPGR3R-gFsRjQ9k5ks&hl=en&ei=VE05Tt_SD8bLhAecvb2jAg&sa=X&oi=book_result&ct=result&resnum=10&ved=0CGUQ6AEwCTgK#v=onepage&q&f=false

other links:-

http://www-uxsup.csx.cam.ac.uk/courses/Fortran/foils_15.pdf

http://en.wikipedia.org/wiki/Fortran_95_language_features

http://www.cs.umbc.edu/~squire/fortranclass/summary.shtml

3 Aug 2011 1:41 (Edited: 3 Aug 2011 1:59) #8716

The following code is portable provided the directory is not on a read only device like a CD-ROM.

Basic approach works in F77 too but without the module wrapper obviously.

module file_utils
contains
   function is_dir_exists(name)
      character (len=*), intent(in) :: name
      logical is_dir_exists

      integer :: icode
         
      ! If the file'abcde' is in the directory, the directory exists
      inquire(file=trim(name)//'/abcde', exist=is_dir_exists)

      ! That's unlikely so use another strategy
      if (.not. is_dir_exists) then
         ! If I can create file 'abcde' in the directory, the directory exists
         open(99,file=trim(name)//'/abcde',iostat=icode)

         ! Directory exists if open was successful, otherwise it doesn't
         is_dir_exists = (icode == 0)

         ! Delete the file
         if (icode == 0) close(99,status='delete')
      end if

   end function

end module file_utils



program anon

   use file_utils
   
   if (is_dir_exists('tmp')) then
      print *, 'Directory exists'
   else
      print *, 'Directory does not exist'
   end if

end program anon
3 Aug 2011 1:55 #8717

This works excellent! Thanks.

Even though the call to system is not documented it works. The following code is the proof: program anon

   use file_utils
   character(len=256) :: dir,sys_cmd
   
   dir = 'c:\\temp\\test1'
   if (is_dir_exists(dir)) then 
      print *, 'Directory exists' 
   else 
      print *, 'Directory does not exist' 
      write(*,*) 'Create the new directory '//trim(dir)
      sys_cmd = 'mkdir '//trim(dir)
      call system(sys_cmd)
   end if 

end program anon

Paul, could you make a comment on the call to system. I could not find it in the documentation. However, it works for both FTN95 and gfortran.

3 Aug 2011 2:00 #8718

You might want to note I added a condition to the close line. Its possible that close on an unopened file is just ignored so its ok without this additional check; I don't have time to check this now.

Do you want the directory creation to be portable too?

3 Aug 2011 2:08 #8719

Is it possible that the result of inquire has to do with evironment variables or something like that? If you like to test the following code, please note that 'c:\blabla' doesn't exist on my PC, but 'c:\homepage' does (so, please replace this path by one that is existing on your PC):

WINAPP 
OPTIONS(INTL) 

PROGRAM TEST 

IMPLICIT NONE 
INCLUDE <WINDOWS.INS> 

logical*2      L

print*,'c:\\blabla (not existing)'
inquire(file='c:\\blabla\',exist=L)
print*,L

print*,'c:\\program files (x86) (existing)'
inquire(file='c:\\program files (x86)\',exist=L)
print*,L

print*,'c:\\homepage (existing)'
inquire(file='c:\\homepage\',exist=L)
print*,L

print*,'c:\\temp (existing)'
inquire(file='c:\\temp\',exist=L)
print*,L

end
3 Aug 2011 2:11 #8720

The directory creation must be portable as well. Are there other options beside a call to system?

The FEM code was initially to be used on a windows system. In the meanwhile we found that the performance and developing to be easier on Linux - at least for our application.

3 Aug 2011 2:35 #8721

Quoted from jjgermis Are there other options beside a call to system?

No, sadly. Maybe there's something in Fortran 2008 for the future.

4 Aug 2011 12:23 #8728

I prefer the FILES@ approach to determine if a directory exists, as if the directory does exists and you have rights to access it, then you will get at least 2 entries; '.' and '..'. My approach to counting the number of files in a directory would exclude these 2 system entries. A directory could have only sub-directories and no files, or no files of the type you want ( eg .txt files). What answer would you want in this case ? I agree with Bruce that the Fortran Standard does not help in this case.

John

4 Aug 2011 6:20 #8733

Here is some C code that can be compiled with SCC...

extern 'C' int count_files_at(char *rootDirectory)
{
  HANDLE hFind;
  WIN32_FIND_DATA findFileData;
  char temp[MAX_PATH], rootDirectoryPattern[MAX_PATH];
  int count = 0;

  if(strchr(rootDirectory, '*'))
  {
    strcpy(rootDirectoryPattern, rootDirectory);
  }
  else
  {
    if(rootDirectory[strlen(rootDirectory)-1] == '\\\')  rootDirectory[strlen(rootDirectory)-1] = '\\0';
    strcpy(rootDirectoryPattern, rootDirectory);
    strcat(rootDirectoryPattern, '\\\\*');
  }

  hFind = FindFirstFile (rootDirectoryPattern, &findFileData);
  if(hFind != INVALID_HANDLE_VALUE)
  {
    do
    {
      strncpy(temp, rootDirectory, strlen(rootDirectory));
      temp[strlen(rootDirectory)] = '\\\';
      temp[strlen(rootDirectory)+1] = '\\0';
      strcat(temp, findFileData.cFileName);
      if (strcmp(findFileData.cFileName, '.') != 0 && strcmp(findFileData.cFileName, '..') != 0)
      {
        if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) ++count;
      }
    } while (FindNextFile (hFind, &findFileData) != 0);
  }
  FindClose(hFind);
  return count;
}
4 Aug 2011 12:43 #8735

Paul, thanks for the C-code.

Regarding the call to SYSTEM. It works with Silverfrost FTN95. However, it is not found in the documentation. According to the documentation and comments in this thread CISSUE should be use. For my unterstanding the call to SYSTEM should not work. What is the truth on this?

Please login to reply.