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