2012-03-01 16 views
5

Sto provando a verificare che esista una directory che utilizza Fortan90. Su vari siti ho trovato:Verificare se esiste una directory o

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 

Tuttavia, inquire rendimenti False se la directory esiste e se eseguo questo codice due volte, ricevo un messaggio di errore

non può fare dir, file esiste già

Se uso:

inquire(file='./docs/test', exist=dir_e) 

con un test di file esistente, inquire restituisce true.

Come posso verificare l'esistenza di una directory? Sto usando Ubuntu 11.04 e il compilatore ifort.

+3

Come soluzione alternativa si potrebbe anche usare 'mkdir -p'. –

+0

Sei sicuro di usare l'inquisizione prima del secondo tentativo se? Funziona per me bene per i miei due compilatori (Oracle Solaris Studio, Gfortran). Puoi anche provare 'file = './Docs'', che funziona anche per me. –

risposta

5

Il seguente dovrebbe funzionare:

INQUIRE (DIRECTORY=dir, EXIST=ex [, DIRSPEC=dirspec] [, ERR=label] [, IOSTAT=i-var]) 

Non ho ifort su questa macchina, quindi non posso provarlo.

Addendum: il codice pubblicato originariamente funziona con gfortran. L'istruzione DIRECTORY funziona con ifort ma non con gfortran.

E nel caso di ulteriori informazioni di controllo: http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/win/compiler_f/lref_for/source_files/rfinquir.htm#rfinquir

+0

Non lo consiglierei a causa di estensioni non standard. Ci sono stati troppi casi, in cui ha significato difficoltà nel porting verso un altro compilatore, che può essere necessario in modo imprevisto. –

+0

Ovviamente sono d'accordo con Vladimir, ma il problema è che apparentemente il percorso gfortran non funziona. Una rapida occhiata sullo standard F95 mostra che non vi è alcun comportamento per le directory nella dichiarazione di richiesta. Se mi sono perso qualcosa (o è stato aggiunto a uno standard successivo) fammi sapere. – Azrael3000

+1

Ma sulle directory linux ci sono solo file con un accesso alla directory. Forse ifort non ama il trailing '/ .'. –

2

Il Fortran standard di 95, 2003 e il 2008 non specificano, come informarsi dovrebbero trattare le directory. Dalla mia esperienza sotto Linux, gfortran li tratta come file, ifort no. L'istruzione di directory è una caratteristica proprietaria di ifort e dovrebbe quindi essere evitata.

Il più sicuro sarebbe verificare un file nella suddetta directory.

3

La maggior parte delle volte, si controlla se la directory esiste per scrivere qualcosa in essa. Quello che faccio è semplicemente creare la directory. Se esiste già non c'è nessun problema.

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

Ecco una subroutine uso spesso - si usa il condizionale hai chiesto:

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 

A seconda di quale compilatore si utilizza, si dovrà decidere quale di questi condizionali è giusto per tu.

Purtroppo, non ho accesso a nagfor e non so come tratta le directory.

0

Ho avuto lo stesso problema. Se vuoi un compilatore in modo indipendente, puoi provare ad aprire un piccolo file all'interno della directory. L'istruzione aperto permette il codice per passare ad una particolare linea (specificata da err =) se l'istruzione apertura fallisce:

! 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 

noti che questo non è infallibile, in quanto si presume "dir" ha il trascinamento "/"o" ​​\ "a seconda del sistema operativo in uso.

+0

Come si riconosce la differenza tra la directory non esistente e non è possibile eliminare/creare il file? – francescalus

+0

Questo codice non lo fa, quindi il codice di errore dice che non esiste o non potrebbe scrivere lì. Non conosco un modo per dire la differenza. – gordon

0

Un'altra soluzione non portabile è quella di lasciare che la shell (Bash, in questo caso) fare il lavoro:

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

Crea una directory. Come si ottiene da questo se esiste una directory se non è necessario essere creati? Com'è meglio di 'mkdir -p'? –

+0

Ho capito che la domanda/l'esempio dell'OP è che voleva creare una directory. Hai ragione, 'mkdir -p' è quasi equivalente a questo test esplicito. Una differenza è che se 'docs' esiste come un file normale, questo metodo non genera un messaggio di errore. Questo può o non può essere vantaggioso. – Frontier

1

Si potrebbe utilizzare routine C per testare i file:

lato C (OK con ifort e gfortran su Win32 e 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; 
    } 
} 

lato 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 

Come utilizzare in una routine Fortran:

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

Vantaggio: funziona per qualsiasi tipo di file e fornisce ulteriori elementi di informazione come la modalità (lettura/scrittura/esecuzione permesso) e l'ora di creazione.

Problemi correlati