File Paths in Fortran

The filepath module in Fortran is not a standard feature, so we’ll use string manipulation and system-specific functions to handle file paths. This example demonstrates how to work with file paths in Fortran, focusing on portability between operating systems.

program file_paths
    use, intrinsic :: iso_fortran_env, only: error_unit
    implicit none
    
    character(len=:), allocatable :: p, filename, ext
    logical :: is_absolute
    integer :: last_separator, dot_position

    ! Join should be used to construct paths in a portable way.
    ! In Fortran, we'll use a simple concatenation function.
    p = join_path("dir1", "dir2", "filename")
    print *, "p:", p

    ! Demonstrate path normalization
    print *, join_path("dir1//", "filename")
    print *, join_path("dir1/../dir1", "filename")

    ! Split a path into directory and file components
    call split_path(p, last_separator)
    print *, "Dir(p):", p(:last_separator)
    print *, "Base(p):", p(last_separator+1:)

    ! Check if a path is absolute
    is_absolute = is_path_absolute("dir/file")
    print *, is_absolute
    is_absolute = is_path_absolute("/dir/file")
    print *, is_absolute

    filename = "config.json"

    ! Extract file extension
    dot_position = index(filename, ".", back=.true.)
    if (dot_position > 0) then
        ext = filename(dot_position:)
        print *, ext
    else
        print *, "No extension found"
    end if

    ! Remove file extension
    if (dot_position > 0) then
        print *, filename(:dot_position-1)
    else
        print *, filename
    end if

    ! Finding relative paths is complex and system-dependent in Fortran
    print *, "Relative path operations are not directly supported"

contains

    function join_path(path1, path2, path3) result(joined)
        character(len=*), intent(in) :: path1, path2
        character(len=*), intent(in), optional :: path3
        character(len=:), allocatable :: joined
        character(len=1) :: separator

        separator = '/'  ! Use '/' for Unix-like systems, '\' for Windows

        if (present(path3)) then
            joined = trim(path1) // separator // trim(path2) // separator // trim(path3)
        else
            joined = trim(path1) // separator // trim(path2)
        end if
    end function join_path

    subroutine split_path(path, last_separator)
        character(len=*), intent(in) :: path
        integer, intent(out) :: last_separator
        integer :: i

        last_separator = 0
        do i = len(path), 1, -1
            if (path(i:i) == '/' .or. path(i:i) == '\') then
                last_separator = i
                exit
            end if
        end do
    end subroutine split_path

    function is_path_absolute(path) result(is_absolute)
        character(len=*), intent(in) :: path
        logical :: is_absolute

        is_absolute = (len(path) > 0 .and. (path(1:1) == '/' .or. path(1:1) == '\'))
    end function is_path_absolute

end program file_paths

This Fortran program demonstrates basic file path operations:

  1. We define a join_path function to concatenate path components, similar to the filepath.Join function in the original example.

  2. Path splitting is done using a split_path subroutine, which finds the last separator in the path.

  3. We check if a path is absolute using the is_path_absolute function.

  4. File extension extraction and removal are performed using string manipulation.

  5. Relative path operations are not directly supported in standard Fortran, so we’ve omitted that part.

To run the program, save it as file_paths.f90 and compile it using a Fortran compiler:

$ gfortran file_paths.f90 -o file_paths
$ ./file_paths

Note that Fortran doesn’t have built-in modules for advanced file path manipulation, so this example uses basic string operations. For more complex path handling, you might need to use system-specific libraries or write more elaborate functions.