Проверьте, существует ли каталог или нет - PullRequest
6 голосов
/ 01 марта 2012

Я пытаюсь проверить, существует ли каталог, используя Fortan90. На разных сайтах я нашел:

logical :: dir_e
inquire(file='./docs/.', exist=dir_e)

if ( dir_e ) then
  write(*,*) "dir exists!"
else
  ! workaround: it calls an extern program...
  call system('mkdir docs')
end if

Однако inquire возвращает False независимо от того, существует каталог или нет, и если я выполняю этот код дважды, я получаю сообщение об ошибке

не может создать каталог, файл уже существует

Если я использую:

inquire(file='./docs/test', exist=dir_e)

с существующим тестом файла, inquire возвращает true.

Как я могу проверить наличие каталога? Я использую Ubuntu 11.04 и компилятор ifort.

Ответы [ 7 ]

5 голосов
/ 18 февраля 2014

Стандарты Fortran 95, 2003 и 2008 не указывают, как справка должна обращаться с каталогами. Из моего опыта работы с Linux gfortran рассматривает их как файлы, а ifort - нет. Оператор каталога является частной функцией ifort, поэтому его следует избегать.

Самое безопасное - проверить файл в указанном каталоге.

4 голосов
/ 02 марта 2012

Должно работать следующее:

INQUIRE (DIRECTORY=dir, EXIST=ex [, DIRSPEC=dirspec] [, ERR=label] [, IOSTAT=i-var] )

У меня нет ifort на этом компьютере, поэтому я не могу его протестировать.

Приложение: отправленный код изначально работает с gfortran.Оператор DIRECTORY работает с ifort, но не с gfortran.

А в случае получения дополнительной информации проверьте: http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/win/compiler_f/lref_for/source_files/rfinquir.htm#rfinquir

3 голосов
/ 28 февраля 2014

В большинстве случаев проверяется, существует ли каталог, чтобы что-то записать в него. Я просто создаю каталог. Если он уже существует, проблем нет.

     CALL system("mkdir video")
     CALL chdir("video")
     CALL getcwd(path)
2 голосов
/ 07 августа 2015

Вы можете использовать подпрограммы C для проверки файлов:

C сторона (ОК с ifort и gfortran на Win32 и Linux 32/64)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#if defined(_WIN32) && defined(__INTEL_COMPILER)
#  include "dirent_windows.h"
#else
#  include <dirent.h>
#endif

void file_info(const char*filename,int*mode,int*exist,int*time){
  int k;
  struct stat buf;
  k=stat(filename,&buf);
  if(k != 0) {
    *mode=0;
    *exist=0;
    *time=0;
  }else{
    *mode=buf.st_mode;
    if(*mode == 0) *exist=0; else *exist=1;
    *time=buf.st_mtime;
  }
}

Сторона Fortran:

MODULE file

  USE iso_c_binding

  INTERFACE
    SUBROUTINE file_info(filename,mode,exist,time) BIND(C,name="file_info")
      USE iso_c_binding
      CHARACTER(kind=C_CHAR),INTENT(in) :: filename(*)
      INTEGER(C_INT),INTENT(out) :: mode,exist,time
    END SUBROUTINE
  END INTERFACE

END MODULE

Как использовать в рутине на Фортране:

..
use file
use iso_c_binding
...
integer(c_int) :: mode,exist,time
...
call file_info("./docs"//char(0),mode,exist,time)

Преимущество: он работает для любого типа файла и предоставляет дополнительные фрагменты информации, такие как режим (разрешение на чтение / запись / выполнение) ивремя создания.

0 голосов
/ 06 августа 2015

Другое непереносимое решение - позволить оболочке (в данном случае Bash) выполнить работу:

call system('[[ ! -e docs ]] && mkdir docs')
0 голосов
/ 11 июня 2015

У меня была такая же проблема.Если вам нужен независимый от компилятора способ сделать это, вы можете попробовать открыть небольшой файл в каталоге.Оператор open позволяет коду переходить на определенную строку (указанную в err =), если оператор open терпит неудачу:

! Tests whether the directory exists
subroutine checkdir(dir)
       implicit none
       character(len=*), intent(in) :: dir
       integer :: unitno

       ! Test whether the directory exists
       open(newunit=unitno,file=trim(dir)//'deleteme.txt',status='replace',err=1234)
       close (unitno)
       return

       ! If doesn't exist, end gracefully
1234   write(*,*) 'Data directory, '//trim(dir)//' does not exist or could not write there!'
       STOP

end subroutine

Обратите внимание, что это не надежно, поскольку предполагается, что "dir" имеетзавершающий "/" или "\" в зависимости от используемой ОС.

0 голосов
/ 10 июля 2014

Вот подпрограмма, которую я часто использую - она ​​использует условие, о котором вы спрашивали:

subroutine create_directory( newDirPath )
    ! Author:  Jess Vriesema
    ! Date:    Spring 2011
    ! Purpose: Creates a directory at ./newDirPath

    implicit none

    character(len=*), intent(in) :: newDirPath
    character(len=256)           :: mkdirCmd
    logical                      :: dirExists

    ! Check if the directory exists first
!   inquire( file=trim(newDirPath)//'/.', exist=dirExists )  ! Works with gfortran, but not ifort
    inquire( directory=newDirPath, exist=dirExists )         ! Works with ifort, but not gfortran


    if (dirExists) then
!      write (*,*) "Directory already exists: '"//trim(newDirPath)//"'"
    else
        mkdirCmd = 'mkdir -p '//trim(newDirPath)
        write(*,'(a)') "Creating new directory: '"//trim(mkdirCmd)//"'"
        call system( mkdirCmd )
    endif
end subroutine create_directory

В зависимости от того, какой компилятор вы используете, вам придется решить, какой из этих условий вам подходит.

К сожалению, у меня нет доступа к nagfor и я не знаю, как он обрабатывает каталоги.

...