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.
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).
directory_entries/2¶
directory_entries(Dir, Entry) — enumerate directory entries one at a time via backtracking.
File Metadata¶
file_size/2¶
file_size(Path, Size) — unify Size with file size in bytes (integer).
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.
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.
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.
split_path/3¶
split_path(Path, Directory, Filename) — split a path into its directory and filename parts.
file_extension/2¶
file_extension(Path, Extension) — unify Extension with the file extension (including the dot, e.g. ".csv"). Empty string if no extension.
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)
)