Skip to content

File Operations

Lamia provides a file namespace for direct filesystem operations: reading, writing, appending, checking existence, and finding files by pattern — all without involving an LLM.

Overview

# Find files by pattern
csv_files = file.glob("./data/*.csv")

# Check if a file exists
if file.exists("./config.json"):
    content = file.read("./config.json")

# Read a file
content = file.read("./config.json")

# Write to a file
file.write("./output.txt", "Hello, World!")

# Append to a file
file.append("./log.txt", "New entry\n")

API

file.read(path, encoding="utf-8")

Read file contents and return as a string.

content = file.read("./data.csv")
settings = file.read("./config.yaml", encoding="utf-8")
legacy = file.read("./old_data.txt", encoding="latin-1")

Parameters:

Parameter Type Default Description
path str required File path to read
encoding str "utf-8" File encoding

Returns: File content as a string.

file.write(path, content, encoding="utf-8")

Write content to a file. Creates the file if it doesn't exist, overwrites if it does.

file.write("./output.txt", "Hello, World!")
file.write("./data.json", json.dumps({"key": "value"}))
file.write("./legacy.csv", csv_content, encoding="latin-1")

Parameters:

Parameter Type Default Description
path str required File path to write
content str required Content to write
encoding str "utf-8" File encoding

file.append(path, content, encoding="utf-8")

Append content to an existing file. Creates the file if it doesn't exist.

file.append("./log.txt", f"[{timestamp}] Event occurred\n")
file.append("./results.csv", "new_row,data,here\n")

Parameters:

Parameter Type Default Description
path str required File path to append to
content str required Content to append
encoding str "utf-8" File encoding

file.glob(pattern)

Find files matching a glob pattern. Returns a sorted list of matching file paths. Use | to OR multiple patterns.

csv_files = file.glob("./data/*.csv")
configs = file.glob("./**/*.json|./**/*.yaml")
scripts = file.glob("./**/*.lm|./**/*.hu")
specific = file.glob("config.json|settings.yaml|.env")

Parameters:

Parameter Type Default Description
pattern str required Glob pattern, use \| for OR

Returns: Sorted list of matching file paths (empty list if no matches).

Pattern syntax: - * — matches any characters within a single directory - ** — matches across directories (recursive) - ? — matches a single character - | — OR: combines multiple patterns ("*.lm|*.hu|config.json")

file.exists(path)

Check if a file exists. Returns True if the file exists, False otherwise.

if file.exists("./data.csv"):
    data = file.read("./data.csv")
else:
    file.write("./data.csv", "header1,header2\n")

Parameters:

Parameter Type Default Description
path str required File path to check

Returns: True if the file exists, False otherwise.

Patterns

Batch file processing

Use file.glob() to find and process multiple files at once:

# Process all CSV files in a directory
for path in file.glob("./reports/*.csv"):
    content = file.read(path)
    # process each file...

# Find multiple file types at once
configs = file.glob("./**/*.json|./**/*.yaml")

# Find specific files by name
important = file.glob("config.json|settings.yaml|.env|README.md")

# Check if any matching files exist
if file.glob("./inbox/*.txt"):
    # process inbox...

Conditional file operations

Use file.exists() to branch logic based on whether a file is already present:

if file.exists("./output.csv"):
    file.append("./output.csv", f"{name},{score}\n")
else:
    file.write("./output.csv", "name,score\n")
    file.append("./output.csv", f"{name},{score}\n")

CSV operations

csv_path = "./results.csv"

# Initialize CSV with headers if it doesn't exist
if not file.exists(csv_path):
    file.write(csv_path, "timestamp,status,message\n")

# Append rows
file.append(csv_path, f"{timestamp},success,Completed\n")

Safe config loading

config_path = "./config.json"

if file.exists(config_path):
    raw = file.read(config_path)
    # parse and use config
else:
    # use defaults or create initial config
    file.write(config_path, '{"retries": 3}')

Common Mistakes

Do NOT use Python's built-in open() or with open() — Lamia scripts use the file.* API:

# ❌ NOT RECOMMENDED — Lamia syntax is preferred
with open("data.txt", "r") as f:
    content = f.read()

# ❌ NOT RECOMMENDED — Lamia syntax is preferred
try:
    content = file.read("data.txt")
except FileNotFoundError:
    content = ""

# ✅ CORRECT
if file.exists("data.txt"):
    content = file.read("data.txt")
else:
    content = ""

# ✅ CORRECT — simple read
content = file.read("data.txt")

# ✅ CORRECT — write
file.write("data.txt", "hello")

Comparison with Other File Mechanisms

Lamia has three ways to work with files, each for a different purpose:

Mechanism Purpose Example
file.glob/exists/read/write/append Direct filesystem I/O file.write("out.txt", data)
-> File(...) LLM-generated content saved to disk def report() -> File(HTML, "report.html")
with files(...) Inject file content into LLM prompts {@resume.pdf}

When to use file.*

Use file.glob(), file.exists(), file.read(), file.write(), file.append() when you have content already and want to perform straightforward filesystem operations — no LLM involved.

# Read a queue, modify it, write it back
content = file.read("./queue.txt")
lines = content.strip().split('\n')
lines.append("new_item")
file.write("./queue.txt", '\n'.join(lines) + '\n')

When to use -> File(...)

Use -> File(Type, path) when you want the LLM to generate content and save it directly to a file with optional type validation.

def generate_report() -> File(HTML, "report.html"):
    "Create a quarterly sales report"

When to use with files(...)

Use with files(...) when you want to inject file content into LLM prompts via {@filename} syntax.

with files("~/Documents/"):
    def summarize():
        "Summarize {@report.pdf}"

Reading Files with Type Conversion

To read a file and parse it into a typed Python object, use the -> Type syntax:

data = "./config.json" -> JSON       # Returns a dict
config = "./settings.yaml" -> YAML   # Returns a dict

This is different from file.read() which always returns a raw string.