ReadonlyatWhether the current position is at (or beyond) the end of the file.
ReadonlyisWhether the file is still open.
ReadonlylastThe error from the most recent failed operation on this file, or null if no operation has failed.
The object has a code (a POSIX error name such as "ENOENT", "EACCES", "EAGAIN", or "EILSEQ"
for invalid UTF-8) and a human-readable message. It is not cleared by successful operations.
ReadonlymodeThe mode the file was opened with (e.g. "r", "w+").
ReadonlypathThe absolute path of the file, with symbolic links resolved. Updated by rename().
ReadonlypositionThe current byte offset within the file. 0 if the file is closed.
ReadonlysizeThe current size of the file in bytes. 0 if the file is closed.
Get metadata for the open file.
Returns the same object as hs.fs.attributes(), but reads it from the open file itself, so it
remains accurate after the file has been renamed or removed.
Attributes object, or null on failure.
Close the file. Calling close() on a file that is already closed does nothing.
true on success (or if the file was already closed), false on failure.
Copy the file on disk to a new path, including its metadata. The original stays open.
Fails if destination already exists, if the file has been removed, or (while the file is open)
with "ESTALE" if path no longer refers to it.
The path for the copy. ~ is expanded.
true on success, false on failure.
Call a function for each remaining line of the file.
Line endings are stripped. The callback may return false to stop early, leaving the position
immediately after the last line delivered. If the callback throws, iteration stops and the
exception propagates to the caller.
The callback may use this file: if it moves the position or changes the file's contents, iteration
continues from the current position with the file as it now is. If it closes the file, iteration
stops and eachLine returns false with lastError.code === "EBADF".
Called once per line. Return false to stop.
true if iteration completed or was stopped by the callback returning false; false on error, if the callback threw, or if the file was closed during iteration.
Force any written data out to stable storage (fsync).
Writes are not buffered by HSFile, so other processes see them immediately; flush() additionally
guarantees they survive a crash or power loss.
true on success, false on failure.
Take an advisory lock on the file (flock).
Advisory locks only affect other processes that also use locking; they do not prevent reads or writes.
Locks are released by unlock() or when the file is closed.
Optionalshared: booleanPass true for a shared (read) lock, which several processes may hold at once. Defaults to false (an exclusive lock).
Optionalwait: booleanPass true to wait until the lock is available. This blocks Hammerspoon until the lock is acquired. Defaults to false, which fails immediately with lastError.code === "EAGAIN" if the lock is held elsewhere.
true if the lock was acquired, false otherwise.
Read UTF-8 text from the current position.
When byteCount is given, at most that many bytes are read. If that would split a multi-byte
UTF-8 character, reading stops before the character so it is returned whole by the next read.
If the data is not valid UTF-8, null is returned, the position is left unchanged, and
lastError.code is "EILSEQ". Use readBytes() for binary data.
Like Lua's f:read("a"), reading to the end of the file never signals end of file: at the end it
returns "". Only a read with a byteCount returns null at end of file, so loop on read(n).
OptionalbyteCount: numberMaximum number of bytes to read. Omit (or pass 0) to read to the end of the file.
The text read; "" when reading to the end of the file from its end; null for a byteCount read at end of file, or on error.
Read raw bytes from the current position.
As with read(), reading to the end of the file returns an empty Uint8Array at the end, while a
read with a byteCount returns null at end of file.
OptionalbyteCount: numberMaximum number of bytes to read. Omit (or pass 0) to read to the end of the file.
The bytes read; empty when reading to the end of the file from its end; null for a byteCount read at end of file, or on error.
Read the next line of UTF-8 text.
Both \n and \r\n line endings are recognised. A final line with no trailing newline is still returned.
OptionalkeepNewline: booleanPass true to keep the line ending in the returned string. Defaults to false.
The line, or null at end of file or on error.
Read all remaining lines of the file into an array. Line endings are stripped. On error the position is left unchanged.
An array of lines (empty at end of file), or null on error.
Remove the file from disk.
The file stays open: you can keep reading and writing it until close(), after which its storage is freed.
While the file is open, this fails with "ESTALE" if path no longer refers to it, so a file that
has since replaced it is never removed by mistake.
true on success, false on failure.
Rename (move) the file on disk. The file stays open and path is updated.
Both paths must be on the same volume. By default this fails if newPath already exists.
While the file is open, this fails with "ESTALE" if path no longer refers to it (for example
because another process moved it and put something else in its place), rather than acting on
the wrong file. Once the file is closed, it acts on whatever is at path.
The new path. ~ is expanded.
Optionaloverwrite: booleanPass true to atomically replace any existing file at newPath. Defaults to false.
true on success, false on failure.
Move the current position back to the start of the file.
true on success, false on failure.
Move the current position.
Unlike Lua's f:seek(), the offset is required: to find the current position or the size of the
file without moving, use the position and size properties.
The byte offset (an integer), relative to whence. May be negative for "cur" and "end".
Optionalwhence: "set" | "cur" | "end""set" (from the start of the file), "cur" (from the current position), or "end" (from the end of the file). Defaults to "set".
The new position, or null on failure (including EINVAL if offset is missing or not an integer).
Set the POSIX permission bits of the file.
The permission bits, as an integer between 0 and 0o7777, e.g. 0o600. Use an octal literal: decimal 600 is a different (and unusual) mode.
true on success, false on failure (including EINVAL if permissions is missing or out of range).
Set the access and modification times of the file.
The argument order matches hs.fs.touch() and Hammerspoon v1: access time first.
OptionalaccessDate: numberSeconds since the Unix epoch (fractions allowed). Defaults to now.
OptionalmodificationDate: numberSeconds since the Unix epoch (fractions allowed). Defaults to accessDate.
true on success, false on failure (including EINVAL for a NaN, infinite, or out-of-range timestamp).
Truncate (or extend with zero bytes) the file to the given length. The position is not changed.
Optionallength: numberThe new length in bytes. Omit (or pass 0) to empty the file.
true on success, false on failure.
Release a lock taken with lock().
true on success, false on failure.
Write a string to the file as UTF-8 at the current position (or at the end, for files opened in "a"/"a+" mode).
The text to write.
true on success, false on failure.
Write raw bytes to the file.
The bytes to write. Any typed array is accepted; its underlying bytes are written as-is.
true on success, false on failure (including if bytes is not a typed array or ArrayBuffer).
Write a string followed by a newline (\n).
The text to write.
true on success, false on failure.
An open file, created by
hs.fs.open()orhs.fs.tempFile().HSFileis the equivalent of a Luaiofile handle in Hammerspoon v1. It supports reading and writing text (UTF-8) or binary data (Uint8Array), seeking, truncating, advisory locking, and operating on the underlying path (rename, duplicate, remove). All reads and writes go straight to the file descriptor with no user-space buffering, sopositionis always exact and data written is immediately visible to other processes. Useflush()if you also need it forced to stable storage. Operations that fail returnnullorfalseand setlastErrorto an object of the form{code: "ENOENT", message: "No such file or directory"}.lastErroris not cleared by successful calls, so only consult it after a call has reported failure. Alwaysclose()files when you are finished with them, or usehs.fs.withFile(), which closes the file for you. Any files still open are closed when your configuration is reloaded.