Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Io 在Fortran中循环部分编号的文件_Io_Fortran_Filenames - Fatal编程技术网

Io 在Fortran中循环部分编号的文件

Io 在Fortran中循环部分编号的文件,io,fortran,filenames,Io,Fortran,Filenames,我想在目录/dir1/中循环文件名。例如,此目录中的文件部分遵循编号模式 数据001_abjdfsd.dat 数据002_dchuwe.dat 数据003_jnvkfi.dat 等等。前8个字符遵循编号模式,格式均为“.dat”,其余字符串为任意格式。请注意,文件名中的字符串长度不是固定的。我可能可以在shell脚本中使用通配符轻松地完成它。如何在Fortran 90中循环这些文件?这里有一个完整的独立于平台(但不是傻瓜式的!)解决方案(应该在Linux/Windows/Mac中工作)。请注

我想在目录
/dir1/
中循环文件名。例如,此目录中的文件部分遵循编号模式

  • 数据001_abjdfsd.dat
  • 数据002_dchuwe.dat
  • 数据003_jnvkfi.dat

等等。前8个字符遵循编号模式,格式均为“.dat”,其余字符串为任意格式。请注意,文件名中的字符串长度不是固定的。我可能可以在shell脚本中使用通配符轻松地完成它。如何在Fortran 90中循环这些文件?

这里有一个完整的独立于平台(但不是傻瓜式的!)解决方案(应该在Linux/Windows/Mac中工作)。请注意,您将需要Fortran 2008编译器。以下模块中的函数
getFileList(searchText、order、excludeText)
将为您提供当前目录(或
searchText
中提供的目录)中的文件列表。请注意,
searchText
将被传递到命令行环境以搜索文件。因此,通配符可以用于文件搜索。另外两个参数是可选的:
order
确定文件应按什么顺序列出。此函数仅支持两个订单:
name
date
。第三个参数
excludeText
是您不希望存在于函数列出的任何文件中的文本。在输出端,函数返回一个类型为
dynamicString
的结构,该结构包含所有请求文件的列表,按请求的顺序排列,每个文件可能具有不同的名称长度。我在这封信的底部附上了一个测试文件

module ModFileList

  implicit none

  integer, parameter, private :: maxFileRecordLength = 2047

  type DynamicString
    character (len=:), allocatable :: record
  end type DynamicString

contains

!*********************************************************************
!*********************************************************************

  function getFileList(searchText,order,excludeText)

    implicit none
    character(len=*)   , intent(in)           :: searchText
    character(len=*)   , intent(in), optional :: order
    character(len=*)   , intent(in), optional :: excludeText
    type(DynamicString), allocatable          :: getFileList(:)
    character(len=:)   , allocatable          :: command,filename,orderLowerCase
    character(len=maxFileRecordLength)        :: record
    integer                                   :: iunit,counter,iostat,nRecord,nskip
    character(8)                              :: date
    character(10)                             :: time
    logical                                   :: exist

    if (present(order)) then
      orderLowerCase = getLowerCase(order)
    else
      orderLowerCase = 'name'
    end if

    if (getSlash()=='\') then  ! it's Windows cmd
      if (orderLowerCase=='name') then  ! ascending in name
        command = 'dir /b /a-d ' // searchText
      elseif (orderLowerCase=='date') then   ! oldest will be first
        command = 'dir /b /a-d /o:d ' // searchText
      else
        write(*,*) '    FATAL: In Misc@getFileList()'
        write(*,*) '           The requested file order is not supported.'
        write(*,*) '           order = ', orderLowerCase
        write(*,*) 'Program aborted.'
      end if
      if (present(excludeText)) then
        command = command // " | findstr /v /i " // trim(adjustl(excludeText))
      end if
    else
      if (orderLowerCase=='name') then  ! ascending in name
        command = 'ls -1 ' // searchText
      elseif (orderLowerCase=='date') then   ! oldest will be first
        command = 'ls -tr ' // searchText
      else
        write(*,*) '    FATAL: In Misc@getFileList()'
        write(*,*) '           The requested file order is not supported.'
        write(*,*) '           order = ', orderLowerCase
        write(*,*) 'Program aborted.'
      end if
      if (present(excludeText)) then
        command = command // " --ignore=" // trim(adjustl(excludeText))
      end if
    end if

    ! generate a brand new, non-existing filename
    counter = 0
    do
      counter = counter + 1
      call date_and_time(date,time)
      filename = date // '_' // time // '_' // 'getFileList_' // int2str(counter) // '.temp'
      inquire(file=filename,exist=exist)    ! check if the file already exists
      if (exist) cycle
      exit
    end do
    call execute_command_line(command//' > '//filename)

    nRecord = getNumRecordInFile(filename)

    ! check filename is not among records
    nskip = 0
    open(newunit=iunit,file=filename,status='old')
    do counter = 1,nRecord
      read(iunit,'(A)',iostat=iostat) record
      if(iostat==0) then
        if(filename==trim(adjustl(record))) nskip = nskip + 1
      else
        write(*,*) '    FATAL (1): In Misc@getFileList()'
        write(*,*) '               Error occurred while reading file.'
        write(*,*) 'Program aborted.'
        stop
      end if
    end do
    close(iunit)

    allocate(getFileList(nRecord-nskip))
    open(newunit=iunit,file=filename,status='old')
    do counter = 1,nRecord
      read(iunit,'(A)',iostat=iostat) record
      if(iostat==0) then
        if (filename/=trim(adjustl(record))) getFileList(counter)%record = trim(adjustl(record))
      else
        write(*,*) '    FATAL (2): In Misc@getFileList()'
        write(*,*) '               Error occurred while reading file.'
        write(*,*) 'Program aborted.'
        stop
      end if
    end do
    close(iunit)

    if (getSlash()=='\') then  ! it's Windows cmd
      command = 'del '//filename
    else
      command = 'rm '//filename
    end if
    call execute_command_line(command)

  end function getFileList

!*********************************************************************
!*********************************************************************

  pure function getLowerCase(string)
    implicit None
    character(*), intent(in) :: string
    character(len(string))   :: getLowerCase
    character(26), parameter :: lowerCase = 'abcdefghijklmnopqrstuvwxyz', upperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    integer                  :: ic, i
    ! capitalize each letter if it is lowercase
    getLowerCase = string
    do i = 1, len(string)
        ic = INDEX(upperCase, string(i:i))
        if (ic > 0) getLowerCase(i:i) = lowerCase(ic:ic)
    end do
  end function getLowerCase

!*********************************************************************
!*********************************************************************

  function getNumRecordInFile(filename)
    implicit none
    character(len=*), intent(in) :: filename
    character(len=8)             :: record
    integer                      :: getNumRecordInFile,iunit,iostat
    open(newunit=iunit,file=filename,status='old')
    getNumRecordInFile = 0
    do
      read(iunit,'(A)',iostat=iostat) record
      if(iostat==0) then
        getNumRecordInFile = getNumRecordInFile + 1
        cycle
      elseif(iostat<0) then
        exit
      else
        write(*,*) 'FATAL error occurred reading file in Misc in getNumRecordInFile().'
        write(*,*) 'Program aborted.'
        stop
      end if
    end do
    close(iunit)
  end function getNumRecordInFile

!*********************************************************************
!*********************************************************************
  character(len=1) function getSlash()
    implicit none
    character(len=7) :: os
    call get_environment_variable('OS',os)
    if (os=='Windows') then
      getSlash = '\'
    else
      getSlash = '/'
    end if
  end function getSlash

!*********************************************************************
!*********************************************************************

  pure function int2str(integerIn,formatIn)
    implicit none
    integer     , intent(in)           :: integerIn
    character(*), intent(in), optional :: formatIn
    character(:), allocatable          :: int2str
    integer                            :: i,length
    character(len=63)                  :: thisFormat
    if (present(formatIn)) then
      write(thisFormat,formatIn) integerIn
      int2str = trim(adjustl(thisFormat))
    else
      do i=1,63
        if(abs(integerIn)<10**i) then
          length = i
          if (integerIn<0) length = length + 1
          exit
        end if
      end do
      allocate(character(length) :: int2str)
      write(thisFormat,'(1I63)') length
      thisFormat = '(1I' // trim(adjustl(thisFormat)) // ')'
      write(int2str,thisFormat) integerIn
    end if
  end function int2str

!*********************************************************************
!*********************************************************************  

end module ModFileList
如果编译并运行此测试文件,则输出应类似于以下内容:

2 files detected containing *.f90 :
main.f90
mod_FileList.f90

查看内在的
execute\u命令行
。您可以列出文件并重定向到一个文件。只需从新创建的文件中读取文件名。另一个选项是在命令行使用通配符通过命令行传递文件名。您可以使用命令
command\u argument\u count
get\u command\u argument
以编程方式检索这些参数。这是自Fortran 2003以来的标准。例如,请参阅gfortran的文档,如果您使用的是英特尔Fortran,
IFPORT
模块中的
GETFILEINFOQQ
可以返回与指定模式匹配的文件名的文件信息,并允许使用通配符。我们是否希望此人不想搜索“rm-rf*?为什么在主程序中包含
include'mod_FileList'
行?即使在将包含的文件名更改为“ModFileList”之后,我也没有删除这一行,但还是出现了一个错误,或者这是代码的“不防白痴”特性的一部分?我使用gfortran。我刚刚测试了测试文件,它与gfortran一起工作非常好。从测试程序中删除
包括'mod_FileList'
,并用上面给出的模块替换它(将模块直接插入测试程序顶部。您可以在此处进行测试:它工作正常:注意,您需要更改编译器默认选项以支持F2008。防白痴部分引用了上面的@francescalus重要注释。
2 files detected containing *.f90 :
main.f90
mod_FileList.f90