Skip to content

Files Module

The py.files standard library module provides relational predicates for file and directory operations: existence checks, listing, metadata, CRUD, path manipulation, and temporary files. For higher-level file formats, see the JSON, CSV, and YAML modules.

The implementation lives in clausal/modules/py/files.py.


Import

-import_from(py.files, [file_exists, directory_files, read_file_to_string,
                        write_string_to_file, join_path, make_directory_path])

Or via module import:

-import_module(py.files)
# then use py.files.file_exists("data.csv"), py.files.join_path(A_, B_, P_), etc.

Text in, text out

A path or content argument may be a string ("data.csv") or an atom ('data.csv', or a Python str passed in with ++). Every text the module hands back — file names, joined paths, file contents, extensions — is a string: directory_files on a directory holding a.py and b.txt gives ["a.py", "b.txt"], which Python sees as [('$chars', 'a.py'), ('$chars', 'b.txt')] (use clausal.to_python for plain strs).


Errors

A file-system failure in an action raises an ISO error (ruled 2026-10-02; these predicates used to fail):

Failure Error
the path does not exist (or goes through a file: a.txt/b) existence_error(source_sink, Path)
no permission; a directory where a file is needed, or a file where a directory is needed; the name is already taken; the directory is not empty permission_error(Action, source_sink, Path)
too many open files; no space left resource_error(file_descriptors); resource_error(disk_space)

Action is open for reading, writing and listing (ISO open/4), modify for delete_file, delete_directory, rename_file, and create for make_directory, make_directory_path, temp_file, temp_directory. Path is the argument as written; for rename_file and copy_file it is the argument the failure is about. The three tests below (file_exists, directory_exists, path_exists) never raise: their failure is the answer, also for a path the process may not look at.

Predicates

Existence Checks

file_exists/1

file_exists(Path) — succeeds if Path is a regular file.

check_config <- file_exists("config.json")

directory_exists/1

directory_exists(Path) — succeeds if Path is a directory.

path_exists/1

path_exists(Path) — succeeds if Path exists (file, directory, or other).

Directory listing

directory_files/2

directory_files(Dir, Files) — unify Files with a sorted list of filenames in Dir. Deterministic (one solution, full list).

list_dir(DIR, FILES) <- directory_files(DIR, FILES)

directory_entries/2

directory_entries(Dir, Entry) — enumerate directory entries one at a time via backtracking.

print_entries(DIR) <- (directory_entries(DIR, ENTRY), writeln_text(ENTRY), fail)

File Metadata

file_size/2

file_size(Path, Size) — unify Size with file size in bytes (integer).

is_large_file(PATH) <- (file_size(PATH, SIZE), SIZE > 1000000)

file_modification_time/2

file_modification_time(Path, Time) — unify Time with the modification timestamp (float, seconds since epoch).

Destructive Operations

All destructive predicates require ground path arguments.

delete_file/1

delete_file(Path) — delete a file. A missing file is existence_error(source_sink, Path); a directory is permission_error(modify, source_sink, Path).

delete_directory/1

delete_directory(Path) — delete an empty directory. A missing one is existence_error(source_sink, Path); a non-empty one, or a file, permission_error(modify, source_sink, Path).

rename_file/2

rename_file(Old, New) — rename or move a file or directory.

copy_file/2

copy_file(Source, Destination) — copy a file (preserves metadata). Not for directories.

Directory Creation

make_directory/1

make_directory(Path) — create a directory. A path that already exists is permission_error(create, source_sink, Path); a missing parent existence_error(source_sink, Path).

make_directory_path/1

make_directory_path(Path) — create a directory and all parents (like mkdir -p). Succeeds even if the directory already exists.

ensure_output_dir <- make_directory_path("output/reports/2024")

File I/O

read_file_to_string/2

read_file_to_string(Path, Contents) — read an entire file as a UTF-8 string. A missing file is existence_error(source_sink, Path); content that is not UTF-8 fails.

read_config(PATH, CONTENT) <- (file_exists(PATH), read_file_to_string(PATH, CONTENT))

write_string_to_file/2

write_string_to_file(Path, Contents) — write a string to a file, overwriting any existing content.

append_string_to_file/2

append_string_to_file(Path, Contents) — append a string to a file. Creates the file if it does not exist.

Path Manipulation

absolute_path/2

absolute_path(Relative, Absolute) — resolve a relative path to an absolute path.

join_path/3

join_path(Base, Relative, Joined) — join two path components.

output_path(DIR, NAME, PATH) <- join_path(DIR, NAME, PATH)

split_path/3

split_path(Path, Directory, Filename) — split a path into its directory and filename parts.

get_filename(PATH, NAME) <- split_path(PATH, _, NAME)

file_extension/2

file_extension(Path, Extension) — unify Extension with the file extension (including the dot, e.g. ".csv"). Empty string if no extension.

is_python_file(PATH) <- file_extension(PATH, ".py")

Temporary Files

temp_file/1

temp_file(Path) — create a temporary file and unify Path with its path. The caller is responsible for cleanup.

temp_directory/1

temp_directory(Path) — create a temporary directory and unify Path with its path. The caller is responsible for cleanup.


Example

This example uses include to select files by extension.

-import_from(py.files, [file_exists, directory_files, read_file_to_string,
                        write_string_to_file, join_path, make_directory_path,
                        file_extension])

save_output(DIR, NAME, CONTENT) <- (
    make_directory_path(DIR),
    join_path(DIR, NAME, PATH),
    write_string_to_file(PATH, CONTENT)
)

python_files(DIR, FILES) <- (
    directory_files(DIR, ALL),
    include(is_py, ALL, FILES)
)
is_py(F) <- file_extension(F, ".py")

read_config(PATH, CONTENT) <- (
    file_exists(PATH),
    read_file_to_string(PATH, CONTENT)
)