2012-03-01 89 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'。 – 2012-03-02 13:10:06

+0

你确定在第二次尝试之前使用查询吗?对于我的两个编译器(Oracle Solaris Studio,Gfortran)而言,它对我来说都很好。你也可以尝试'file ='。/ docs'',这也适用于我。 – 2012-03-02 13:19:52

回答

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

我不会推荐取决于非标准扩展名。有太多的情况,这意味着移植到另一个编译器时会遇到困难,这可能是意外需要的。 – 2012-03-02 08:57:52

+0

我当然同意弗拉基米尔,但问题是,显然gfortran路线不起作用。对F95标准的快速浏览表明查询语句中的目录没有任何行为。如果我遗漏了一些东西(或者是以后的标准),请告诉我。 – Azrael3000 2012-03-02 09:20:38

+1

但是在Linux上,目录只是具有目录登录的文件。也许ifort不喜欢尾随的'/ .'。 – 2012-03-02 13:23:10

2

Fortran标准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 2015-06-11 18:40:39

+0

此代码不会,因此错误代码说不存在或不能写在那里。我不知道有什么方法可以说明差异。 – gordon 2015-06-12 19:45:27

0

另一个非便携式解决方案是让壳(猛砸,在这种情况下)做的工作:

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

这会创建一个目录。如果你不需要创建一个目录,你如何从中获得?这比“mkdir -p”更好吗? – 2015-08-06 10:36:21

+0

我明白OP的问题/例子是他想创建一个目录。你是对的,'mkdir -p'几乎等于这个明确的测试。一个区别是,如果'docs'作为常规文件存在,则此方法不会引发错误消息。这可能会或可能不会有利。 – Frontier 2015-08-07 17:31:52

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) 

优势:它适用于任何类型的文件,并提供类似的模式信息的附加件(读/写/执行权限)和创建时间。

相关问题