Skip to content

feat: exists to return the type of a path #1026

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

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions doc/specs/stdlib_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,45 @@ Formats all the arguments into a nice error message, utilizing the constructor o

---

## `is_regular_file` - Test if a path is a regular file

### Status

Experimental

### Description

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

### Syntax

`result = ` [[stdlib_system(module):is_regular_file(function)]]`(path)`

### Class

Function

### Arguments

`path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument.

### Return values

The function returns a `logical` value:

- `.true.` if the path matches an existing regular file.
- `.false.` otherwise, or if path does not exist.

### Example

```fortran
{!example/system/example_is_regular_file.f90!}
```

---

## `is_directory` - Test if a path is a directory

### Status
Expand All @@ -506,6 +545,7 @@ Experimental
### Description

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

### Syntax
Expand Down Expand Up @@ -535,6 +575,46 @@ The function returns a `logical` value:

---

## `is_symlink` - Test if a path is a symbolic link.

### Status

Experimental

### Description

This function checks if a specified file system path is a symbolic link to either a file or a directory.
Use [[stdlib_system(module):is_regular_file(function)]] and [[stdlib_system(module):is_directory(function)]] functions
to check further if the link is to a file or a directory respectively.
It is designed to work across multiple platforms. On Windows, paths with both forward `/` and backward `\` slashes are accepted.

### Syntax

`result = ` [[stdlib_system(module):is_symlink(function)]]`(path)`

### Class

Function

### Arguments

`path`: Shall be a character string containing the file system path to evaluate. It is an `intent(in)` argument.

### Return values

The function returns a `logical` value:

- `.true.` if the path matches an existing regular file.
- `.false.` otherwise, or if the path does not exist.

### Example

```fortran
{!example/system/example_is_symlink.f90!}
```

---

## `make_directory` - Creates an empty directory

### Status
Expand Down Expand Up @@ -720,6 +800,54 @@ Subroutine

---

## `exists` - Checks if a path exists in the filesystem

### Status

Experimental

### Description

This function makes a system call (syscall) to retrieve metadata for the specified path and determines its type.
It can distinguish between the following path types:

- Regular File
- Directory
- Symbolic Link

It returns a constant representing the detected path type, or `type_unknown` if the type cannot be determined.
Any encountered errors are handled using `state_type`.

### Syntax

`fs_type = [[stdlib_system(module):exists(function)]] (path [, err])`

### Class

Function

### Arguments

`path`: Shall be a character string containing the path. It is an `intent(in)` argument.

`err`(optional): Shall be of type `state_type`, and is used for error handling. It is an `optional, intent(out)` argument.

### Return values

`fs_type`: An `intent(out), integer` parameter indicating the type. The possible values are:
- `fs_type_unknown`: 0 => an unknown type
- `fs_type_regular_file`: 1 => a regular file
- `fs_type_directory`: 2 => a directory
- `fs_type_symlink`: 3 => a symbolic link

`err`(optional): It is an optional state return flag. If not requested and an error occurs, an `FS_ERROR` will trigger an error stop.

```fortran
{!example/system/example_exists.f90!}
```

---

## `null_device` - Return the null device file path

### Status
Expand Down
5 changes: 4 additions & 1 deletion example/system/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
ADD_EXAMPLE(get_runtime_os)
ADD_EXAMPLE(delete_file)
ADD_EXAMPLE(is_directory)
ADD_EXAMPLE(null_device)
ADD_EXAMPLE(os_type)
ADD_EXAMPLE(process_1)
Expand All @@ -19,3 +18,7 @@ ADD_EXAMPLE(path_dir_name)
ADD_EXAMPLE(make_directory)
ADD_EXAMPLE(remove_directory)
ADD_EXAMPLE(cwd)
ADD_EXAMPLE(exists)
ADD_EXAMPLE(is_regular_file)
ADD_EXAMPLE(is_directory)
ADD_EXAMPLE(is_symlink)
30 changes: 30 additions & 0 deletions example/system/example_exists.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
! Illustrate the usage of `exists`
program example_exists
use stdlib_system, only: exists, fs_type_unknown, fs_type_regular_file, &
fs_type_directory, fs_type_symlink
use stdlib_error, only: state_type
implicit none

type(state_type) :: err

! Path to check
character(*), parameter :: path = "path/to/check"
! To get the type of the path
integer :: t

t = exists(path, err)

if (err%error()) then
! An error occured, print it
print *, err%print()
end if

! switching on the type returned by `exists`
select case (t)
case (fs_type_unknown); print *, "Unknown type!"
case (fs_type_regular_file); print *, "Regular File!"
case (fs_type_directory); print *, "Directory!"
case (fs_type_symlink); print *, "Symbolic Link!"
end select
end program example_exists

14 changes: 14 additions & 0 deletions example/system/example_is_regular_file.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
! Demonstrate usage of `is_regular_file`
program example_is_regular_file
use stdlib_system, only: is_regular_file
implicit none

character(*), parameter :: path = "path/to/check"

! Test if path is a regular file
if (is_regular_file(path)) then
print *, "The specified path is a regular file."
else
print *, "The specified path is not a regular file."
end if
end program example_is_regular_file
20 changes: 20 additions & 0 deletions example/system/example_is_symlink.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
! Demonstrate usage of `is_symlink`
program example_is_symlink
use stdlib_system, only: is_symlink, is_directory
implicit none

character(*), parameter :: path = "path/to/check"

! Test if path is a symbolic link
if (is_symlink(path)) then
print *, "The specified path is a symlink."
! Further check if it is linked to a file or a directory
if (is_directory(path)) then
print *, "Further, it is a link to a directory."
else
print *, "Further, it is a link to a file."
end if
else
print *, "The specified path is not a symlink."
end if
end program example_is_symlink
Loading
Loading