Skip to content

Commit 21c65ab

Browse files
authored
feat: exists to return the type of a path (#1026)
2 parents efb26ca + 95b47ec commit 21c65ab

File tree

8 files changed

+650
-30
lines changed

8 files changed

+650
-30
lines changed

doc/specs/stdlib_system.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,45 @@ Formats all the arguments into a nice error message, utilizing the constructor o
497497

498498
---
499499

500+
## `is_file` - Test if a path is a regular file
501+
502+
### Status
503+
504+
Experimental
505+
506+
### Description
507+
508+
This function checks if a specified file system path is a regular file.
509+
It follows symbolic links and returns the status of the `target`.
510+
It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted.
511+
512+
### Syntax
513+
514+
`result = ` [[stdlib_system(module):is_file(function)]]`(path)`
515+
516+
### Class
517+
518+
Function
519+
520+
### Arguments
521+
522+
`path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument.
523+
524+
### Return values
525+
526+
The function returns a `logical` value:
527+
528+
- `.true.` if the path matches an existing regular file.
529+
- `.false.` otherwise, or if path does not exist.
530+
531+
### Example
532+
533+
```fortran
534+
{!example/system/example_is_file.f90!}
535+
```
536+
537+
---
538+
500539
## `is_directory` - Test if a path is a directory
501540

502541
### Status
@@ -506,6 +545,7 @@ Experimental
506545
### Description
507546

508547
This function checks if a specified file system path is a directory.
548+
It follows symbolic links and returns the status of the `target`.
509549
It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted.
510550

511551
### Syntax
@@ -535,6 +575,46 @@ The function returns a `logical` value:
535575

536576
---
537577

578+
## `is_symlink` - Test if a path is a symbolic link.
579+
580+
### Status
581+
582+
Experimental
583+
584+
### Description
585+
586+
This function checks if a specified file system path is a symbolic link to either a file or a directory.
587+
Use [[stdlib_system(module):is_file(function)]] and [[stdlib_system(module):is_directory(function)]] functions
588+
to check further if the link is to a file or a directory respectively.
589+
It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted.
590+
591+
### Syntax
592+
593+
`result = ` [[stdlib_system(module):is_symlink(function)]]`(path)`
594+
595+
### Class
596+
597+
Function
598+
599+
### Arguments
600+
601+
`path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument.
602+
603+
### Return values
604+
605+
The function returns a `logical` value:
606+
607+
- `.true.` if the path matches an existing regular file.
608+
- `.false.` otherwise, or if the path does not exist.
609+
610+
### Example
611+
612+
```fortran
613+
{!example/system/example_is_symlink.f90!}
614+
```
615+
616+
---
617+
538618
## `make_directory` - Creates an empty directory
539619

540620
### Status
@@ -720,6 +800,54 @@ Subroutine
720800

721801
---
722802

803+
## `exists` - Checks if a path exists in the filesystem
804+
805+
### Status
806+
807+
Experimental
808+
809+
### Description
810+
811+
This function makes a system call (syscall) to retrieve metadata for the specified path and determines its type.
812+
It can distinguish between the following path types:
813+
814+
- Regular File
815+
- Directory
816+
- Symbolic Link
817+
818+
It returns a constant representing the detected path type, or `type_unknown` if the type cannot be determined.
819+
Any encountered errors are handled using `state_type`.
820+
821+
### Syntax
822+
823+
`fs_type = [[stdlib_system(module):exists(function)]] (path [, err])`
824+
825+
### Class
826+
827+
Function
828+
829+
### Arguments
830+
831+
`path`: Shall be a character string containing the path. It is an `intent(in)` argument.
832+
833+
`err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `optional, intent(out)` argument.
834+
835+
### Return values
836+
837+
`fs_type`: An `intent(out), integer` parameter indicating the type. The possible values are:
838+
- `fs_type_unknown`: 0 => an unknown type
839+
- `fs_type_regular_file`: 1 => a regular file
840+
- `fs_type_directory`: 2 => a directory
841+
- `fs_type_symlink`: 3 => a symbolic link
842+
843+
`err`(optional): It is an optional state return flag. If not requested and an error occurs, an `FS_ERROR` will trigger an error stop.
844+
845+
```fortran
846+
{!example/system/example_exists.f90!}
847+
```
848+
849+
---
850+
723851
## `null_device` - Return the null device file path
724852

725853
### Status

example/system/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
ADD_EXAMPLE(get_runtime_os)
22
ADD_EXAMPLE(delete_file)
3-
ADD_EXAMPLE(is_directory)
43
ADD_EXAMPLE(null_device)
54
ADD_EXAMPLE(os_type)
65
ADD_EXAMPLE(process_1)
@@ -19,3 +18,7 @@ ADD_EXAMPLE(path_dir_name)
1918
ADD_EXAMPLE(make_directory)
2019
ADD_EXAMPLE(remove_directory)
2120
ADD_EXAMPLE(cwd)
21+
ADD_EXAMPLE(exists)
22+
ADD_EXAMPLE(is_file)
23+
ADD_EXAMPLE(is_directory)
24+
ADD_EXAMPLE(is_symlink)

example/system/example_exists.f90

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
! Illustrate the usage of `exists`
2+
program example_exists
3+
use stdlib_system, only: exists, fs_type_unknown, fs_type_regular_file, &
4+
fs_type_directory, fs_type_symlink
5+
use stdlib_error, only: state_type
6+
implicit none
7+
8+
type(state_type) :: err
9+
10+
! Path to check
11+
character(*), parameter :: path = "path/to/check"
12+
! To get the type of the path
13+
integer :: t
14+
15+
t = exists(path, err)
16+
17+
if (err%error()) then
18+
! An error occured, print it
19+
print *, err%print()
20+
end if
21+
22+
! switching on the type returned by `exists`
23+
select case (t)
24+
case (fs_type_unknown); print *, "Unknown type!"
25+
case (fs_type_regular_file); print *, "Regular File!"
26+
case (fs_type_directory); print *, "Directory!"
27+
case (fs_type_symlink); print *, "Symbolic Link!"
28+
end select
29+
end program example_exists
30+

example/system/example_is_file.f90

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
! Demonstrate usage of `is_file`
2+
program example_is_file
3+
use stdlib_system, only: is_file
4+
implicit none
5+
6+
character(*), parameter :: path = "path/to/check"
7+
8+
! Test if path is a regular file
9+
if (is_file(path)) then
10+
print *, "The specified path is a regular file."
11+
else
12+
print *, "The specified path is not a regular file."
13+
end if
14+
end program example_is_file
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
! Demonstrate usage of `is_symlink`
2+
program example_is_symlink
3+
use stdlib_system, only: is_symlink, is_directory
4+
implicit none
5+
6+
character(*), parameter :: path = "path/to/check"
7+
8+
! Test if path is a symbolic link
9+
if (is_symlink(path)) then
10+
print *, "The specified path is a symlink."
11+
! Further check if it is linked to a file or a directory
12+
if (is_directory(path)) then
13+
print *, "Further, it is a link to a directory."
14+
else
15+
print *, "Further, it is a link to a file."
16+
end if
17+
else
18+
print *, "The specified path is not a symlink."
19+
end if
20+
end program example_is_symlink

0 commit comments

Comments
 (0)