-
Notifications
You must be signed in to change notification settings - Fork 191
Add filesystem interaction #874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
d760b5f
27b9ece
0dcfe43
96593b5
c1830df
84f36f1
0642aff
e58f4b8
7e91c7c
21739b7
eeeb634
9da3ea7
d913f93
9119970
84fca8b
e701d68
bf14f0a
ff9242a
b0ce565
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
! SPDX-Identifier: MIT | ||
|
||
!> Interaction with the filesystem. | ||
module stdlib_io_filesystem | ||
use stdlib_string_type, only: string_type | ||
implicit none | ||
private | ||
|
||
public :: exists, list_dir, run, temp_dir | ||
|
||
character(*), parameter :: temp_dir = 'temp' | ||
character(*), parameter :: listed_contents = temp_dir//'/listed_contents.txt' | ||
|
||
contains | ||
|
||
!> Version: experimental | ||
!> | ||
!> Whether a file or directory exists at the given path. | ||
!> [Specification](../page/specs/stdlib_io.html#exists) | ||
logical function exists(filename) | ||
!> Name of the file or directory. | ||
character(len=*), intent(in) :: filename | ||
|
||
inquire(file=filename, exist=exists) | ||
|
||
#if defined(__INTEL_COMPILER) | ||
if (.not. exists) inquire(directory=filename, exist=exists) | ||
#endif | ||
end | ||
|
||
!> Version: experimental | ||
!> | ||
!> List files and directories of a directory. Does not list hidden files. | ||
!> [Specification](../page/specs/stdlib_io.html#list_dir) | ||
subroutine list_dir(dir, files, iostat, iomsg) | ||
!> Directory to list. | ||
character(len=*), intent(in) :: dir | ||
!> List of files and directories. | ||
type(string_type), allocatable, intent(out) :: files(:) | ||
!> Status of listing. | ||
integer, optional, intent(out) :: iostat | ||
!> Error message. | ||
character(len=:), allocatable, optional, intent(out) :: iomsg | ||
|
||
integer :: unit, stat | ||
character(len=256) :: line | ||
|
||
stat = 0 | ||
|
||
if (.not. exists(temp_dir)) then | ||
call run('mkdir '//temp_dir, stat) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that under Windows OS, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a very pragmatic solution, but I think it should be fine for now |
||
if (stat /= 0) then | ||
if (present(iostat)) iostat = stat | ||
if (present(iomsg)) iomsg = "Failed to create temporary directory '"//temp_dir//"'." | ||
return | ||
end if | ||
end if | ||
|
||
call run('ls '//dir//' > '//listed_contents, stat) | ||
minhqdao marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (stat /= 0) then | ||
if (present(iostat)) iostat = stat | ||
if (present(iomsg)) iomsg = "Failed to list files in directory '"//dir//"'." | ||
return | ||
end if | ||
|
||
open(newunit=unit, file=listed_contents, status='old', action='read', iostat=stat) | ||
if (stat /= 0) then | ||
if (present(iostat)) iostat = stat | ||
if (present(iomsg)) iomsg = "Failed to open file '"//listed_contents//"'." | ||
return | ||
end if | ||
|
||
allocate(files(0)) | ||
do | ||
read(unit, '(A)', iostat=stat) line | ||
if (stat /= 0) exit | ||
files = [files, string_type(line)] | ||
end do | ||
close(unit, status="delete") | ||
end | ||
|
||
!> Version: experimental | ||
!> | ||
!> Run a command in the shell. | ||
!> [Specification](../page/specs/stdlib_io.html#run) | ||
subroutine run(command, iostat, iomsg) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe an option to redirect the command output (stdout, stderr) to a string variable would be very useful. It is being done in the fpm version of this function already. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it slightly exceeds the scope of this PR but it can easily be done in a follow-up PR |
||
!> Command to run. | ||
character(len=*), intent(in) :: command | ||
!> Status of the operation. | ||
integer, intent(out), optional :: iostat | ||
!> Error message. | ||
character(len=:), allocatable, intent(out), optional :: iomsg | ||
|
||
integer :: exitstat, cmdstat | ||
character(len=256) :: cmdmsg | ||
|
||
if (present(iostat)) iostat = 0 | ||
exitstat = 0; cmdstat = 0 | ||
|
||
call execute_command_line(command, exitstat=exitstat, cmdstat=cmdstat, cmdmsg=cmdmsg) | ||
if (exitstat /= 0 .or. cmdstat /= 0) then | ||
if (present(iostat)) then | ||
if (exitstat /= 0) then | ||
iostat = exitstat | ||
else | ||
iostat = cmdstat | ||
end if | ||
end if | ||
if (present(iomsg) .and. trim(adjustl(cmdmsg)) /= '') iomsg = cmdmsg | ||
end if | ||
end | ||
end |
Uh oh!
There was an error while loading. Please reload this page.