fortran - validar - Comprobar si existe un directorio o no
verificar existencia de archivo en shell (7)
Estoy intentando verificar que existe un directorio usando Fortan90. En varios sitios encontré:
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
Sin embargo, inquire
devuelve False
si el directorio existe o no y si ejecuto este código dos veces, aparece un mensaje de error
no se puede hacer dir, el archivo ya existe
Si uso:
inquire(file=''./docs/test'', exist=dir_e)
con una prueba de archivo existente, inquire
devuelve true
.
¿Cómo puedo verificar la existencia de un directorio? Estoy usando ubuntu 11.04 y el compilador ifort.
Lo siguiente debería funcionar:
INQUIRE (DIRECTORY=dir, EXIST=ex [, DIRSPEC=dirspec] [, ERR=label] [, IOSTAT=i-var] )
No tengo ifort en esta máquina, así que no puedo probarlo.
Adición: el código publicado originalmente funciona con gfortran. La instrucción DIRECTORY
funciona con ifort pero no con gfortran.
Y en caso de obtener más información, consulte: http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/win/compiler_f/lref_for/source_files/rfinquir.htm#rfinquir
El estándar Fortran 95, 2003 y 2008 no especifica cómo debe tratar la consulta los directorios. Desde mi experiencia en Linux, gfortran los trata como archivos, ifort no. La instrucción de directorio es una característica propia de ifort y, por lo tanto, debe evitarse.
Lo más seguro sería probar un archivo en dicho directorio.
La mayoría de las veces, uno comprueba si el directorio existe para escribir algo en él. Lo que hago es simplemente crear el directorio. Si ya existe, no hay problema.
CALL system("mkdir video")
CALL chdir("video")
CALL getcwd(path)
Aquí hay una subrutina que uso a menudo: usa el condicional sobre el que preguntaste:
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
Dependiendo del compilador que use, tendrá que decidir cuál de esos condicionales es el adecuado para usted.
Lamentablemente, no tengo acceso a nagfor
y no sé cómo trata los directorios.
Yo tuve el mismo problema. Si desea una forma independiente de compilación, puede intentar abrir un pequeño archivo dentro del directorio. La instrucción abierta permite que el código salte a una línea particular (especificada por err =) si falla la instrucción abierta:
! 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
Tenga en cuenta que esto no es infalible, ya que se supone que "dir" tiene el final "/" o "/" dependiendo del sistema operativo que se utilice.
Otra solución no portátil es permitir que el shell (Bash, en este caso) haga el trabajo:
call system(''[[ ! -e docs ]] && mkdir docs'')
Podría usar rutinas C para probar los archivos:
Lado C (OK con ifort y gfortran en Win32 y 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;
}
}
Lado de 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
Cómo usar en una rutina Fortran:
..
use file
use iso_c_binding
...
integer(c_int) :: mode,exist,time
...
call file_info("./docs"//char(0),mode,exist,time)
Ventaja: funciona para cualquier tipo de archivo y proporciona información adicional como el modo (permiso de lectura / escritura / ejecución) y el tiempo de creación.