Module for filesystem operations.

hs.fs provides a comprehensive set of filesystem operations covering file I/O, directory management, path manipulation, metadata access, symbolic links, Finder tags, and macOS-specific features like file bookmarks and Uniform Type Identifiers.

It replaces both Hammerspoon v1's hs.fs module and the functionality that was previously available through Lua's built-in io and file modules.

Reading and writing files

const contents = hs.fs.read("/etc/hosts");           // entire file
const chunk    = hs.fs.read("/etc/hosts", 100, 50);  // 50 bytes from offset 100

hs.fs.readLines("/etc/hosts", function(line) {
    console.log(line);
    return true; // return false to stop early
});

hs.fs.write("/tmp/hello.txt", "Hello, world!\n");
hs.fs.append("/tmp/hello.txt", "More content\n");

Directory operations

hs.fs.mkdir("~/Projects/new-thing");

const files = hs.fs.list("~/Documents");
const all   = hs.fs.listRecursive("~/Documents");

Path utilities

const abs  = hs.fs.pathToAbsolute("~/Library");
const tmp  = hs.fs.temporaryDirectory();
const home = hs.fs.homeDirectory();

Metadata

const info = hs.fs.attributes("/etc/hosts");
// { size: 1234, type: "file", permissions: 420,
//   ownerID: 0, groupID: 0,
//   creationDate: 1700000000.0, modificationDate: 1700001000.0 }

Types

This module does not provide any types.

Properties

This module has no properties.

Methods

hs.fs.read

Read part or all of a file as a UTF-8 string. ```javascript const all = hs.fs.read("/etc/hosts"); // entire file const chunk = hs.fs.read("/etc/hosts", 100, 50); // 50 bytes starting at byte 100 ```


Declaration

hs.fs.read(path, offset, length) -> string

Parameters

  • path string

    Path to the file. `~` is expanded.

  • offset number

    Byte offset to start reading from. Pass `0` (or omit) to read from the beginning.

  • length number

    Maximum number of bytes to read. Pass `0` (or omit) to read to the end of the file.

Return Value

The file contents as a UTF-8 string, or `null` if the file cannot be read.

hs.fs.readLines

Read a file line-by-line, invoking a callback for each line. Lines are delivered with newline characters stripped. Both `\n` and `\r\n` line endings are handled. ```javascript hs.fs.readLines("/etc/hosts", function(line) { if (line.startsWith("#")) return true; // skip comment lines, keep going console.log(line); return true; // return false to stop early }); ```


Declaration

hs.fs.readLines(path, callback) -> boolean

Parameters

  • path string

    Path to the file. `~` is expanded.

  • callback JSValue

    Called once per line with the line text. Return `true` to continue reading, or `false` to stop early.

Return Value

`true` if the file was read successfully (including early stops requested by the callback), or `false` if the file could not be opened.

hs.fs.write

Write a UTF-8 string to a file, creating it or overwriting any existing content. Intermediate directories are not created automatically; use `mkdir` first if needed.


Declaration

hs.fs.write(path, content, inPlace) -> boolean

Parameters

  • path string

    Path to the file. `~` is expanded.

  • content string

    String to write.

  • inPlace boolean

    Whether to write the file in-place or atomically. Defaults to atomically

Return Value

`true` on success, `false` on failure.

hs.fs.append

Append a UTF-8 string to a file, creating it if it does not exist.


Declaration

hs.fs.append(path, content) -> boolean

Parameters

  • path string

    Path to the file. `~` is expanded.

  • content string

    String to append.

Return Value

`true` on success, `false` on failure.

hs.fs.exists

Determine if a filesystem object exists at the given path Unlike `isFile` and `isDirectory`, this follows symlinks.


Declaration

hs.fs.exists(path) -> boolean

Parameters

  • path string

    Path to check. `~` is expanded.

Return Value

`true` if any filesystem entry (file, directory, symlink, etc.) exists at the path.

hs.fs.isFile

Determine if a file exists at the given path This does **not** follow symlinks; a symlink pointing at a file returns `false`.


Declaration

hs.fs.isFile(path) -> boolean

Parameters

  • path string

    Path to check. `~` is expanded.

Return Value

`true` if a regular file (not a directory or symlink) exists at the path.

hs.fs.isDirectory

Determine if a directory exists at the given path This does **not** follow symlinks; a symlink pointing at a directory returns `false`.


Declaration

hs.fs.isDirectory(path) -> boolean

Parameters

  • path string

    Path to check. `~` is expanded.

Return Value

`true` if a directory exists at the path.

hs.fs.isReadable

Determine if a given filesystem path is readable


Declaration

hs.fs.isReadable(path) -> boolean

Parameters

  • path string

    Path to check. `~` is expanded.

Return Value

`true` if the current process can read the file or directory at the path.

hs.fs.isWritable

Determine if a given filesystem path is writable


Declaration

hs.fs.isWritable(path) -> boolean

Parameters

  • path string

    Path to check. `~` is expanded.

Return Value

`true` if the current process can write to the file or directory at the path.

hs.fs.copy

Copy a file or directory to a new location. The destination must not already exist. If `source` is a directory, its entire contents are copied recursively.


Declaration

hs.fs.copy(source, destination) -> boolean

Parameters

  • source string

    Path to the existing file or directory. `~` is expanded.

  • destination string

    Path for the copy. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.move

Move (rename) a file or directory. The destination must not already exist.


Declaration

hs.fs.move(source, destination) -> boolean

Parameters

  • source string

    Path to the existing file or directory. `~` is expanded.

  • destination string

    New path. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.delete

Delete a file or directory. Directories are removed recursively. To remove only an empty directory, use `rmdir` instead.


Declaration

hs.fs.delete(path) -> boolean

Parameters

  • path string

    Path to delete. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.list

List the immediate contents of a directory. Returns bare filenames (not full paths), sorted alphabetically. The `.` and `..` entries are never included.


Declaration

hs.fs.list(path) -> [String]

Parameters

  • path string

    Path to the directory. `~` is expanded.

Return Value

Sorted array of filenames, or `null` if the path cannot be read.

hs.fs.listRecursive

Recursively list all entries under a directory. Returns paths relative to `path`, sorted alphabetically.


Declaration

hs.fs.listRecursive(path) -> [String]

Parameters

  • path string

    Path to the root directory. `~` is expanded.

Return Value

Sorted array of relative paths, or `null` if the path cannot be read.

hs.fs.mkdir

Create a directory, including all necessary intermediate directories. Succeeds silently if the directory already exists.


Declaration

hs.fs.mkdir(path) -> boolean

Parameters

  • path string

    Path of the directory to create. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.rmdir

Remove an empty directory. Fails if the directory is not empty. Use `delete` to remove a non-empty directory recursively.


Declaration

hs.fs.rmdir(path) -> boolean

Parameters

  • path string

    Path of the directory to remove. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.currentDir

Returns the current working directory of the process.


Declaration

hs.fs.currentDir() -> string

Parameters

None

Return Value

Current directory path, or `null` on error.

hs.fs.chdir

Change the current working directory of the process.


Declaration

hs.fs.chdir(path) -> boolean

Parameters

  • path string

    New working directory path. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.pathToAbsolute

Resolve a path to its absolute, canonical form. Expands `~`, resolves `.` and `..`, and follows all symbolic links. Returns `null` if any component of the path does not exist.


Declaration

hs.fs.pathToAbsolute(path) -> string

Parameters

  • path string

    Path to resolve.

Return Value

Absolute canonical path, or `null` if it cannot be resolved.

hs.fs.displayName

Return the localised display name for a file or directory as shown by Finder. For example, `/Library` appears as `"Library"` in Finder even though its on-disk name is the same.


Declaration

hs.fs.displayName(path) -> string

Parameters

  • path string

    Path to the file or directory. `~` is expanded.

Return Value

Display name string, or `null` if the path does not exist.

hs.fs.temporaryDirectory

Returns the temporary directory for the current user.


Declaration

hs.fs.temporaryDirectory() -> string

Parameters

None

Return Value

Temporary directory path (always ends with `/`).

hs.fs.homeDirectory

Returns the home directory for the current user.


Declaration

hs.fs.homeDirectory() -> string

Parameters

None

Return Value

Home directory path string.

hs.fs.urlFromPath

Returns a `file://` URL string for the given path. ```javascript hs.fs.urlFromPath("/tmp/foo.txt") // → "file:///tmp/foo.txt" ```


Declaration

hs.fs.urlFromPath(path) -> string

Parameters

  • path string

    Filesystem path. `~` is expanded.

Return Value

URL string

hs.fs.attributes

Get metadata attributes for a file or directory. Does not follow symbolic links. Use `isSymlink` to detect links before calling this if needed.


Declaration

hs.fs.attributes(path) -> NSDictionary

Parameters

  • path string

    Path to inspect. `~` is expanded.

Return Value

Attributes object, or `null` if the path cannot be accessed.

hs.fs.touch

Update the modification timestamp of a file to the current time. Creates the file if it does not exist (equivalent to the POSIX `touch` command).


Declaration

hs.fs.touch(path) -> boolean

Parameters

  • path string

    Path to the file. `~` is expanded.

Return Value

`true` on success, `false` on failure.

hs.fs.tags

Get the Finder tags assigned to a file or directory.


Declaration

hs.fs.tags(path) -> [String]

Parameters

  • path string

    Path to the file or directory. `~` is expanded.

Return Value

Array of tag name strings, or `null` if no tags are set.

hs.fs.fileUTI

Replace all Finder tags on a file or directory. This function is only available on macOS Tahoe (26) or later.


Declaration

hs.fs.fileUTI(path) -> string

Parameters

  • path string

    Path to the file.

Return Value

`true` on success, `false` on failure.

hs.fs.pathToBookmark

Encode a file path as a persistent bookmark that survives file moves and renames. The returned string is base64-encoded bookmark data that can be stored and later resolved with `pathFromBookmark`.


Declaration

hs.fs.pathToBookmark(path) -> string

Parameters

  • path string

    Path to the file or directory. `~` is expanded.

Return Value

Base64-encoded bookmark string, or `null` on failure.

hs.fs.pathFromBookmark

Resolve a base64-encoded bookmark back to a file path.


Declaration

hs.fs.pathFromBookmark(data) -> string

Parameters

  • data string

    Base64-encoded bookmark string produced by `pathToBookmark`.

Return Value

The current file path, or `null` if the bookmark cannot be resolved.