2012-03-01 5 views
5

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

+3

В качестве обходного пути вы также можете использовать 'mkdir -p'. –

+0

Вы уверены, что используете запрос до второй попытки, если? Он отлично подходит для моих обоих компиляторов (Oracle Solaris Studio, Gfortran). Вы также можете попробовать использовать файл 'file = './Docs'', который также работает для меня. –

ответ

5

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

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

+0

Я бы не рекомендовал в зависимости от нестандартных расширений. Было слишком много случаев, когда это означало трудности с переносом на другой компилятор, который может понадобиться неожиданно. –

+0

Я, конечно, согласен с Владимиром, но проблема в том, что, по-видимому, маршрут gfortran не работает. Быстрый взгляд на стандарт F95 показывает, что поведение каталогов в инструкции запроса отсутствует. Если я что-то пропустил (или добавил к более позднему стандарту), дайте мне знать. – Azrael3000

+1

Но на Linux-каталогах есть только файлы со знаком каталога. Может быть, ifort не любит конечный '/ .'. –

2

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

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

3

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

 CALL system("mkdir video") 
    CALL chdir("video") 
    CALL getcwd(path) 
0

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

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

0

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

! 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 

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

+0

Как вы указываете разницу между не существующим каталогом и невозможностью удалить/создать файл? – francescalus

+0

Этот код не делает, поэтому код ошибки говорит, что он не существует или не может там писать. Я не знаю, как сказать разницу. – gordon

0

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

call system('[[ ! -e docs ]] && mkdir docs') 
+0

Это создает каталог. Как вы получаете от этого, если каталог существует, если вам не нужно создавать? Как это лучше, чем просто 'mkdir -p'? –

+0

Я понял вопрос/пример OP, что он хотел создать каталог. Вы правы, 'mkdir -p' почти эквивалентен этому явному тесту. Одно отличие состоит в том, что если 'docs' существует как обычный файл, этот метод не выдает сообщение об ошибке. Это может быть или не быть выгодным. – Frontier

1

Вы можете использовать процедуры C, чтобы проверить файлы:

C стороны (OK с 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 

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

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

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

Смежные вопросы