- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have created the following to list the contents of a directory. The subroutine, get_directory_contents, returns an array of character strings, which are the names of all of the files/directories within the directory, given the path of the directory in question. The subroutine uses GetFileInfoQQ, and is based heavily on the example in Intel's documentation for that function. This seems to work correctly. See the following example.
program directory_contents
use ifcore
implicit none
integer :: length, i
character(len=80) folder
character (len=:), dimension (:), allocatable :: file_list
write (*, '(a)') ' Enter path of folder to view contents: '
length = getstrqq(folder)
do while (length > 0)
call get_directory_contents(trim(folder), file_list)
do i = 1, size(file_list,1)
write(*,*) file_list(i)
enddo
length = getstrqq(folder)
enddo
deallocate(file_list)
contains
! subroutine to list the contents of a directory
subroutine get_directory_contents(folder, file_list)
use ifport
implicit none
character (len=*), intent(in) :: folder
character (len=:), dimension(:), allocatable, intent (out) :: file_list
character (len=80) :: files
integer (kind=int_ptr_kind()) :: handle
integer (4) :: length
integer :: len_filename, max_len_filename, no_files, istat
character (len=:), allocatable :: filename
type (file$info) :: info
write(files, '(2a)') trim(folder), '/*'
max_len_filename = 0
no_files = 0
handle = file$first
! run through files once to get number of files and length of
! longest filename
do while (.true.)
length = getfileinfoqq(files, info, handle)
if ((handle .eq. file$last) .or. &
(handle .eq. file$error)) then
select case (getlasterrorqq( ))
case (err$nomem)
write (*,*) 'Out of memory'
case (err$noent)
exit
case default
write (*,*) 'Invalid file or path name'
end select
end if
if (info%name=='.' .or. info%name=='..') cycle
len_filename = len_trim(info%name)
max_len_filename = max(max_len_filename, len_filename)
no_files = no_files + 1
end do
! allocate file list and filename as required
allocate (character(len=max_len_filename) :: file_list(no_files), stat=istat)
if (istat/=0) then
stop 'Error allocating file list.'
end if
allocate (character(len=max_len_filename) :: filename, stat=istat)
if (istat/=0) then
stop 'Error allocating filename.'
end if
handle = file$first
no_files = 0
! now actually get the list of files
do while (.true.)
length = getfileinfoqq(files, info, handle)
if ((handle .eq. file$last) .or. &
(handle .eq. file$error)) then
select case (getlasterrorqq( ))
case (err$nomem)
write (*,*) 'out of memory'
case (err$noent)
exit
case default
write (*,*) 'invalid file or path name'
end select
end if
if (info%name=='.' .or. info%name=='..') cycle
filename = trim(info%name)
! update the number of files and assign
no_files = no_files + 1
if (no_files>size(file_list,1)) then
stop 'Length for file list was allocated incorrectly.'
end if
file_list(no_files) = filename
enddo
deallocate(filename)
end subroutine get_directory_contents
end program directory_contents
The problem is that it doesn't seem to be closing files properly. In the example above, you can repeatedly enter directory paths to list the contents of that directory: if I check the number of files open in the process after each iteration of the loop, I see the number of open files steadily increasing. For example, it looks something like the following in my shell:
[sjb@computer ~]$ pidof directory_contents 27754 [sjb@computer ~]$ ls /proc/27754/fd/ | wc -l 3 [sjb@computer ~]$ ls /proc/27754/fd/ | wc -l 13 [sjb@computer ~]$ ls /proc/27754/fd/ | wc -l 45 [sjb@computer ~]$ ls /proc/27754/fd/ | wc -l 219
In my real code, this eventually reaches the open-file limit of the operating system, which means that when I try to open another file, this fails with the error message, 'too many open files.'
I'm aware of the following caveat in the documentation:
GETFILEINFOQQ must be called with the handle until GETFILEINFOQQ sets handle to FILE$LAST, or system resources may be lost.
However, the subroutine does seem to be making it to the FILE$LAST handle. Is there something else that I'm doing wrong here?
Other possibly relevant details:
- I'm compiling with ifort 18.0.1
- This is being compiled on a GNU/Linux cluster
- The operating system is Red Hat Enterprise Linux Server 7.5 (Maipo)
Link Copied
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page