可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to verify that a directory exists using Fortan90. On various sites I found:
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
However, inquire
returns False
whether or not the directory exists and if I execute this code twice, I get an error message
cannot make dir, file already exists
If I use:
inquire(file='./docs/test', exist=dir_e)
with an existing file test, inquire
returns true
.
How can I check for the existence of a directory? I am using ubuntu 11.04 and the ifort compiler.
回答1:
The following should work:
INQUIRE (DIRECTORY=dir, EXIST=ex [, DIRSPEC=dirspec] [, ERR=label] [, IOSTAT=i-var] )
I don't have ifort on this machine so I can't test it.
Addendum: The code posted originally works with gfortran. The DIRECTORY
statement works with ifort but not with gfortran.
And in case for more information check: http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/win/compiler_f/lref_for/source_files/rfinquir.htm#rfinquir
回答2:
The Fortran standard 95, 2003 and 2008 do not specify, how inquire should treat directories. From my experience under Linux, gfortran treats them as files, ifort does not. The directory statement is a proprietary feature of ifort and should therefore be avoided.
The safest would be to test for a file in the said directory.
回答3:
Most of the time, one checks if the directory exists so to write something in it. What I do is just create the directory. If it already exists there is no problem.
CALL system("mkdir video")
CALL chdir("video")
CALL getcwd(path)
回答4:
You could use C routines to test the files :
C side (OK with ifort and gfortran on Win32 and 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 side :
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
How to use in a Fortran routine :
..
use file
use iso_c_binding
...
integer(c_int) :: mode,exist,time
...
call file_info("./docs"//char(0),mode,exist,time)
Advantage : it works for any kind of file and provides additional pieces of information like the mode (read/write/execute permission) and the creation time.
回答5:
Here's a subroutine I use often -- it uses the conditional you asked about:
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
Depending on which compiler you use, you'll have to decide which of those conditionals is right for you.
Unfortunately, I do not have access to nagfor
and don't know how it treats directories.
回答6:
I had the same problem. If you want a compiler independent way of doing this, you can try to open a small file within the directory. The open statement allows for the code to jump to a particular line (specified by err=) if the open statement fails:
! 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
Note that this is not foolproof, as it is assumed "dir" has the trailing "/" or "\" depending on the OS being used.
回答7:
Another non-portable solution is to let the shell (Bash, in this case) do the work:
call system('[[ ! -e docs ]] && mkdir docs')