Проверить, существует ли каталог или нет

Я пытаюсь проверить существование каталога с помощью 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.


person Sebastian    schedule 01.03.2012    source источник
comment
В качестве обходного пути вы также можете использовать mkdir -p.   -  person Vladimir F    schedule 02.03.2012
comment
Вы уверены, что использовали запрос до второй попытки, если? У меня он отлично работает для обоих моих компиляторов (Oracle Solaris Studio, Gfortran). Вы также можете попробовать только file='./docs', это работает и для меня.   -  person Vladimir F    schedule 02.03.2012
comment
Вот пост доктора Фортрана еще в 2006 году, который может представлять интерес: software.intel.com/en-us/forums/.   -  person jvriesem    schedule 18.06.2018


Ответы (7)


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

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

person Azrael3000    schedule 01.03.2012
comment
Я бы не рекомендовал зависеть от нестандартных расширений. Было слишком много случаев, когда это означало трудности с портированием на другой компилятор, который может понадобиться неожиданно. - person Vladimir F; 02.03.2012
comment
Я конечно согласен Владимир, но проблема в том, что видимо гфортран маршрут не работает. Беглый взгляд на стандарт F95 показывает, что в операторе запроса нет никакого поведения для каталогов. Если я что-то пропустил (или это было добавлено к более позднему стандарту), дайте мне знать. - person Azrael3000; 02.03.2012
comment
Но в Linux каталоги — это просто файлы с входом в каталог. Возможно, ifort не любит завершающий /.. - person Vladimir F; 02.03.2012
comment
Истинный. Было бы неплохо, если бы кто-нибудь мог проверить это с помощью ifort. - person Azrael3000; 02.03.2012
comment
Работает с ifort 12.0.2.137 Build 20110112. Проверено просто из любопытства. Не рекомендовал бы использовать. - person milancurcic; 02.03.2012
comment
Мои правки не отображаются по какой-то причине. Вы должны исправить ошибочное ключевое слово EXISTS на EXIST. - person milancurcic; 02.03.2012
comment
Спасибо, что указали на это. ИРО-бот, что именно вы тестировали? Каталог или спецификатор файла? - person Azrael3000; 02.03.2012
comment
@ Azrael3000 Я протестировал нестандартный ключевой аргумент DIRECTORY. Я не тестировал пример, предоставленный ОП. - person milancurcic; 03.03.2012
comment
Я могу убедиться, что inquire(directory=dir, exist=dir_e) работает для ifort 13.0.0 20120731, а inquire(file=trim(dir)//'/.', exist=dir_e) — нет. Если вы знаете, что используете только ifort (как и я), почему бы не использовать его? В отсутствие действительно переносимого и универсального решения, почему бы не использовать решение, которое работает для используемого вами компилятора? Кто-нибудь знает, что работает для nagfor? - person jvriesem; 10.07.2014

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

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

person Mison    schedule 18.02.2014
comment
Если бы избегания функции directory ifort было чем-то, чего следует избегать, мы также хотели бы избежать функции file gfortran, так как обе они не переносимы. Конечно, было бы еще лучше, если бы в будущем стандарте Фортрана были переносимые системные утилиты для подобных вещей. - person jvriesem; 02.05.2018

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

     CALL system("mkdir video")
     CALL chdir("video")
     CALL getcwd(path)
person user1008139    schedule 27.02.2014
comment
Где-то это может сработать, но точно не везде, иначе вопрос не имел бы смысла mkdir tmp mkdir: cannot create directory 'tmp': File exists - person Vladimir F; 05.04.2019

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

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 и я не знаю, как он работает с каталогами.

person jvriesem    schedule 10.07.2014
comment
спасибо, это работает для меня (пример кода gfortran) - person sailfish009; 23.05.2020

Вы можете использовать подпрограммы 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;
  }
}

Фортран сторона:

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

Как использовать в подпрограмме Fortran:

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

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

person Francois Jacq    schedule 07.08.2015

Еще одно непереносимое решение — позволить оболочке (в данном случае Bash) выполнять всю работу:

call system('[[ ! -e docs ]] && mkdir docs')
person Frontier    schedule 06.08.2015
comment
Это создает каталог. Как вы получите от этого, если каталог существует, если вам не нужно создавать? Чем это лучше, чем просто mkdir -p? - person Vladimir F; 06.08.2015
comment
Я понял, что вопрос/пример ОП заключается в том, что он хотел создать каталог. Вы правы, mkdir -p почти эквивалентен этому явному тесту. Одно отличие состоит в том, что если docs существует как обычный файл, этот метод не выдает сообщение об ошибке. Это может быть или не быть выгодным. - person Frontier; 07.08.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» имеет завершающий «/» или «\» в зависимости от используемой ОС.

person gordon    schedule 11.06.2015
comment
Как вы определяете разницу между несуществующим каталогом и невозможностью удалить/создать файл? - person francescalus; 11.06.2015
comment
Этого кода нет, следовательно, код ошибки говорит, что не существует или не может быть записан туда. Я не знаю, как отличить. - person gordon; 12.06.2015