app.file - File Operations API
Read, write, copy, move, delete files and more.
Note: For path type checks (exists, isDirectory, isFile, isSymlink), use the
app.pathmodule.
Basic Operations
app.file.read(path)
Read file contents.
Parameters:
path(string) - File path
Returns: string, error - File contents; returns nil, error on failure
local content, err = app.file.read("/path/to/file.txt")
app.file.write(path, content)
Write content to a file (overwrites existing content).
Parameters:
path(string) - File pathcontent(string) - Content to write
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.write("/path/to/file.txt", "Hello World")
app.file.append(path, content)
Append content to the end of a file.
Parameters:
path(string) - File pathcontent(string) - Content to append
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.append("/path/to/log.txt", "New log line\n")
app.file.copy(src, dest)
Copy a file or directory.
Parameters:
src(string) - Source pathdest(string) - Destination path
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.copy("/source/file.txt", "/dest/file.txt")
app.file.copy("/source/folder", "/dest/folder")
app.file.move(src, dest)
Move or rename a file/directory.
Parameters:
src(string) - Source pathdest(string) - Destination path
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.move("/old/path/file.txt", "/new/path/file.txt")
app.file.move("/path/old_name.txt", "/path/new_name.txt")
app.file.delete(path)
Delete a file or directory.
Parameters:
path(string) - Path to delete
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.delete("/path/to/file.txt")
app.file.mkdir(path)
Create a directory (recursively creates parent directories).
Parameters:
path(string) - Directory path
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.mkdir("/path/to/deep/nested/folder")
File Attributes
app.file.size(path)
Get file size.
Parameters:
path(string) - File path
Returns: number|nil - Size in bytes or nil
local size = app.file.size("/path/to/file.txt")
app.file.creationDate(path)
Get file creation time.
Parameters:
path(string) - File path
Returns: number|nil - Unix timestamp or nil
local created = app.file.creationDate("/path/to/file.txt")
app.file.modificationDate(path)
Get file modification time.
Parameters:
path(string) - File path
Returns: number|nil - Unix timestamp or nil
local modified = app.file.modificationDate("/path/to/file.txt")
app.file.permissions(path)
Get file permission string.
Parameters:
path(string) - File path
Returns: string|nil - Octal permission string or nil
local perms = app.file.permissions("/path/to/file.txt") -- "644"
app.file.attributes(path)
Get all file attributes.
Parameters:
path(string) - File path
Returns: table|nil - Attributes table or nil
local attrs = app.file.attributes("/path/to/file.txt")
-- attrs.size: number
-- attrs.createdDate: number (timestamp)
-- attrs.modifiedDate: number (timestamp)
-- attrs.isDirectory: boolean
-- attrs.permissions: string
app.file.chmod(path, mode)
Change file permissions.
Parameters:
path(string) - File pathmode(number|string) - Permission mode (e.g., 755 or “755”)
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.chmod("/path/to/script.sh", 755)
app.file.chmod("/path/to/script.sh", "755")
Directory Operations
app.file.list(path)
List directory contents.
Parameters:
path(string) - Directory path
Returns: array|nil - Array of file names (without path prefix)
local items = app.file.list("/path/to/folder")
if items then
for _, name in ipairs(items) do
app.log.info(name)
end
end
app.file.glob(directory, pattern)
Match files using a glob pattern (non-recursive).
Parameters:
directory(string) - Directory pathpattern(string) - Glob pattern (e.g., “*.txt”)
Returns: array|nil - Array of full paths
local pngs = app.file.glob("/path/to/folder", "*.png")
app.file.find(directory, options?)
Recursively find files.
Parameters:
directory(string) - Starting directoryoptions(table, optional):name(string) - File name pattern (supports * and ? wildcards)type(string) - Type: “file”, “directory”, or “any” (default)maxDepth(number) - Maximum recursion depth (0 means unlimited, default)limit(number) - Maximum number of results (default 1000)
Returns: array - Array of full paths
-- Find all plist files
local plists = app.file.find("/path/to/folder", {
name = "*.plist",
type = "file",
maxDepth = 5
})
-- Find all directories
local dirs = app.file.find("/path/to/folder", {
type = "directory"
})
Symbolic Links
app.file.link(target, linkPath)
Create a symbolic link.
Parameters:
target(string) - Link target pathlinkPath(string) - Link file path
Returns: boolean, error - Whether successful; returns false, error on failure
local ok, err = app.file.link("/path/to/target", "/path/to/link")
app.file.readlink(path)
Read symbolic link target.
Parameters:
path(string) - Link file path
Returns: string|nil - Target path or nil
local target = app.file.readlink("/path/to/link")
Temporary Files
app.file.temp(options?)
Create a temporary file or directory.
Parameters:
options(table, optional):prefix(string) - Prefix, default"tmp"suffix(string) - Suffix, default""directory(boolean) - Create a directory instead of a file, defaultfalsedir(string) - Base directory, defaults to system temp directory
Returns: string, error - Path of the created temporary file/directory
-- Create a temporary file
local tmpFile, err = app.file.temp()
app.file.write(tmpFile, "Temporary data")
-- Temporary file with suffix
local tmpCsv = app.file.temp({suffix = ".csv"})
-- Create a temporary directory
local tmpDir = app.file.temp({directory = true, prefix = "export"})
Examples
Batch Rename
function MyPlugin:handleRename(context)
local result = app.dialog.form({
title = "Batch Rename",
fields = {
{type = "text", id = "prefix", label = "Prefix", default = ""},
{type = "number", id = "start", label = "Starting Number", default = 1}
}
})
if not result then return end
local num = result.start
for _, file in ipairs(context.selectedFiles) do
local dir = app.path.dirname(file)
local ext = app.path.extension(file)
local newName = string.format("%s%03d.%s", result.prefix, num, ext)
local newPath = app.path.join(dir, newName)
app.file.move(file, newPath)
num = num + 1
end
app.notification.show("Done", "Renamed " .. #context.selectedFiles .. " files")
end
Clean Up Empty Directories
function MyPlugin:handleCleanEmptyDirs(context)
local dirs = app.file.find(context.currentDirectory, {
type = "directory"
})
local deleted = 0
-- Delete from the deepest directories first
for i = #dirs, 1, -1 do
local dir = dirs[i]
local items = app.file.list(dir)
if items and #items == 0 then
if app.file.delete(dir) then
deleted = deleted + 1
end
end
end
app.notification.show("Done", "Deleted " .. deleted .. " empty directories")
end