app.path - Path Utilities API

Path parsing, joining, and special directory access.

Path Component Extraction

app.path.basename(path)

Gets the file name (including extension) from a path.

app.path.basename("/path/to/file.txt")  -- "file.txt"
app.path.basename("/path/to/folder")    -- "folder"

app.path.name(path)

Gets the file name (without extension) from a path.

app.path.name("/path/to/file.txt")      -- "file"
app.path.name("/path/to/archive.tar.gz") -- "archive.tar"

app.path.extension(path)

Gets the file extension (without the dot).

app.path.extension("/path/to/file.txt")      -- "txt"
app.path.extension("/path/to/archive.tar.gz") -- "gz"
app.path.extension("/path/to/folder")         -- ""

app.path.dirname(path)

Gets the parent directory path.

app.path.dirname("/path/to/file.txt")   -- "/path/to"

Path Operations

app.path.join(…)

Joins path components.

app.path.join("/path", "to", "file.txt")     -- "/path/to/file.txt"

app.path.normalize(path)

Normalizes a path (resolves . and ..).

app.path.normalize("/path/../to/./file")     -- "/to/file"

app.path.expandTilde(path)

Expands the tilde to the user’s home directory.

app.path.expandTilde("~/Documents")          -- "/Users/username/Documents"

app.path.absolute(path)

Converts to an absolute path (also expands ~).

app.path.absolute("./file.txt")              -- "/current/dir/file.txt"
app.path.absolute("~/file.txt")              -- "/Users/username/file.txt"

app.path.relative(path, base)

Gets a relative path.

app.path.relative("/a/b/c/file.txt", "/a/b")  -- "c/file.txt"
app.path.relative("/a/b/c", "/a/d")           -- "../b/c"

Path String Checks

app.path.isAbsolute(path)

Checks whether a path is absolute (starts with / or ~).

app.path.isAbsolute("/path/to/file")     -- true
app.path.isAbsolute("~/Documents")       -- true
app.path.isAbsolute("./relative/path")   -- false

app.path.isRelative(path)

Checks whether a path is relative.

app.path.isRelative("./path/to/file")    -- true
app.path.isRelative("/absolute/path")    -- false

app.path.hasExtension(path, ext?)

Checks whether a file has an extension. If ext is specified, checks whether it matches (case-insensitive).

app.path.hasExtension("/file.txt")            -- true (has extension)
app.path.hasExtension("/file.txt", "txt")     -- true
app.path.hasExtension("/file.TXT", "txt")     -- true (case-insensitive)
app.path.hasExtension("/file.txt", ".txt")    -- true (dot prefix also works)
app.path.hasExtension("/folder")              -- false

File System Checks

app.path.exists(path)

Checks whether a path exists.

if app.path.exists("/path/to/file") then
    -- File or directory exists
end

app.path.isDirectory(path)

Checks whether a path is a directory.

if app.path.isDirectory("/path/to/folder") then
    -- Is a directory
end

app.path.isFile(path)

Checks whether a path is a regular file (not a directory or symbolic link).

if app.path.isFile("/path/to/file.txt") then
    -- Is a file
end

Checks whether a path is a symbolic link.

if app.path.isSymlink("/path/to/link") then
    -- Is a symbolic link
end

Path Modification

app.path.withExtension(path, ext)

Changes the extension.

app.path.withExtension("/path/file.txt", "md")     -- "/path/file.md"
app.path.withExtension("/path/file.txt", ".md")    -- "/path/file.md"

app.path.withName(path, name)

Changes the file name (preserving the extension).

app.path.withName("/path/old.txt", "new")          -- "/path/new.txt"

app.path.withBasename(path, basename)

Changes the full file name (including extension).

app.path.withBasename("/path/old.txt", "new.md")   -- "/path/new.md"

app.path.withDirname(path, dirname)

Changes the parent directory.

app.path.withDirname("/old/file.txt", "/new")      -- "/new/file.txt"

Special Directories

Get system special directory paths:

app.path.home()         -- "/Users/username"
app.path.temp()         -- "/var/folders/.../T"
app.path.desktop()      -- "/Users/username/Desktop"
app.path.documents()    -- "/Users/username/Documents"
app.path.downloads()    -- "/Users/username/Downloads"
app.path.applications() -- "/Applications"
app.path.caches()       -- "/Users/username/Library/Caches"
app.path.library()      -- "/Users/username/Library"
app.path.movies()       -- "/Users/username/Movies"
app.path.music()        -- "/Users/username/Music"
app.path.pictures()     -- "/Users/username/Pictures"

Path Analysis

app.path.components(path)

Splits a path into an array of components.

app.path.components("/a/b/c")    -- {"/", "a", "b", "c"}
app.path.components("a/b/c")     -- {"a", "b", "c"}

app.path.split(path)

Splits into directory and file name.

local parts = app.path.split("/path/to/file.txt")
-- { dirname = "/path/to", basename = "file.txt" }

app.path.splitext(path)

Splits into name and extension.

local parts = app.path.splitext("/path/file.txt")
-- { name = "file", extension = "txt" }

Examples

Batch Change Extensions

function MyPlugin:handleChangeExt(context)
    local result = app.dialog.form({
        title = "Change Extension",
        fields = {
            {type = "text", id = "ext", label = "New Extension", default = "md"}
        }
    })
    if not result then return end

    for _, file in ipairs(context.selectedFiles) do
        local newPath = app.path.withExtension(file, result.ext)
        app.file.move(file, newPath)
    end
end

Organize Files into Subdirectories

function MyPlugin:handleOrganize(context)
    local dir = context.currentDirectory

    for _, file in ipairs(context.selectedFiles) do
        local ext = app.path.extension(file)
        if ext ~= "" then
            local subdir = app.path.join(dir, ext:upper())
            if not app.path.exists(subdir) then
                app.file.mkdir(subdir)
            end

            local dest = app.path.join(subdir, app.path.basename(file))
            app.file.move(file, dest)
        end
    end
end
Developer Documentation
User Guide
Getting Started Script Menus FAQ
Script Development
Development Guide
Plugin Development
Quick Start Development Guide Example Plugins
API Reference
Overview API Query Plugin Info Logging Finder Context Plugin Settings Internationalization
UI & Interaction
Dialog Progress Notification Chooser WebView Status Bar Dock
Files & Paths
File Operations Path Utilities Finder Actions Trash Extended Attributes Metadata File Watcher
Data Formats
JSON Plist CSV XML PDF Image
Text & Encoding
String Regex Date & Time Color Crypto
System
Shell Commands Process Application System Info AppleScript Shortcuts
System Info
Network Power/Battery Screen/Appearance Audio Bluetooth Location
Network
HTTP WebSocket URL
Input & Clipboard
Keyboard Mouse Hotkey Clipboard Window
Storage
SQLite Keychain UserDefaults
Media
OCR QR Code
Utilities
Archive UTI Share Timer Wake Lock Thread