std/file
import std/file to use it. Source: src/std/file.iyi at v0.18.0.
Extends the prelude's core File with File::Info, File::Type, File::Permissions, path queries, permissions, timestamps, symlinks, and iteration without external C libraries.
Filealias
pub alias File = ::FileFileclass, reopened
class ::File
def self.basename(path : String | Path, suffix : String | ::Nil = nil) : String
def self.chmod(path : String | Path, mode : Int32) : Nil
def self.chown(path : String | Path, uid : Int32, gid : Int32) : Nil
def self.directory?(path : String | Path) : Bool
def self.dirname(path : String | Path) : String
# A line at a time, off the file as it is read: it read the whole file
# into an array of its lines first, so a log of any size was the
# program's memory twice over before the first line was seen. Lines as
# `read_lines` gives them, without their `\n` or a `\r` before it.
def self.each_line(path : String | Path, &block : (String -> Nil)) : Nil
def self.empty?(path : String | Path) : Bool
# On Windows a file runs by its extension, one of PATHEXT's - what cmd
# and `CreateProcess`'s search go by - and a directory is searchable
# when it can be read. `cmd.exe` answered false: the made-up mode gave
# the execute bit to directories alone.
def self.executable?(path : String | Path) : Bool
def self.expand_path(path : String | Path, base : String | ::Nil = nil) : String
def self.extname(path : String | Path) : String
def self.file?(path : String | Path) : Bool
def self.info(path : String | Path, follow_symlinks : Bool = true) : Info
def self.info?(path : String | Path, follow_symlinks : Bool = true) : Info | ::Nil
def self.join(first : String | Path, second : String | Path, third : String | Path) : String
def self.join(first : String | Path, second : String | Path) : String
def self.join(parts : Array(String)) : String
def self.link(old_path : String | Path, new_path : String | Path) : Nil
# Whether *path* matches the shell-style *pattern*: `*` any run of
# characters within a segment, `**` any run of segments (a whole
# segment of the pattern), `?` one character but a separator, `[abc]`,
# `[a-z]` and `[^...]` one character of a set, `{a,b}` one of the
# branches (nested to ten), and `\` the next character literally. Only
# `/` in the pattern matches a separator. On Windows a name's `\` is a
# separator as well, and a pattern's `\` is one too rather than an
# escape: `Dir.glob` answers with either.
#
# The other library's algorithm (a port of the glob-match crate, after
# research.swtch.com/glob), linear in the name but for braces. This
# had `*` and `?` alone, byte by byte: `*` crossed separators, `?` took
# half of a two-byte character, `[a]` and `{a,b}` were literal text,
# and `*a*a*a*a*a*a*a*a*a*a*b` against forty `a`s did not finish.
def self.match?(path : String | Path, pattern : String) : Bool
def self.read_lines(path : String | Path) : Array(String)
def self.readable?(path : String | Path) : Bool
def self.readlink(path : String | Path) : String
def self.real_path(path : String | Path) : String
def self.rename(old_path : String | Path, new_path : String | Path) : Nil
def self.same?(path1 : String | Path, path2 : String | Path) : Bool
def self.same_content?(path1 : String | Path, path2 : String | Path) : Bool
def self.size(path : String | Path) : Int64
def self.symlink(old_path : String | Path, new_path : String | Path) : Nil
def self.symlink?(path : String | Path) : Bool
# A new, empty file in the temporary directory, and its path.
#
# Made with an exclusive create - `O_CREAT | O_EXCL`, `CREATE_NEW` on
# Windows - which fails when anything is at the path, a symlink
# included, rather than asked whether something is there and written
# after. The name was the process id and a counter, and the file was
# written wherever the path led if nothing was there when asked: a
# symlink planted at the next name in a shared `/tmp` between the
# question and the write sent an upload wherever its owner pointed it.
# The name is sixteen hex digits of the system's randomness now, so it
# cannot be planted in advance either; Windows' `%TEMP%` belongs to the
# user, and there the create's refusal is the guarantee and the name
# needs only to be new. The file is the owner's alone, mode 0600.
def self.tempfile(prefix : String = "tmp", suffix : String = "") : String
# The file is deleted after the block if it is still there: the block
# may have renamed it into place - write to a temporary name, then
# rename, is what the name is for - and `delete` of a path that is gone
# panicked after the block had done its work.
def self.tempfile(prefix : String = "tmp", suffix : String = "", &block : (String -> Nil)) : Nil
# *time* 0 is "now"; any other value is the Unix second both atime and
# mtime are set to.
#
# The darwin branch passed a null `times` to `utimes`, which is the
# kernel's spelling of "now" — so `touch(path, 1)` set the clock's time
# there and the epoch second on Linux, one name with two behaviours
# decided by the platform (SPEC.md III.1.7a). It writes the pair now, in
# the same shape the Linux branch writes its `timespec`s: `timeval` is an
# `Int64` second and an `Int32` microsecond padded to eight, so four
# `Int64` slots are the two structures and the odd slots are the
# microseconds, zero.
def self.touch(path : String | Path, time : Int64 = 0_i64) : Nil
def self.touch?(path : String | Path, time : Int64 = 0_i64) : Bool
def self.truncate(path : String | Path, size : Int64 = 0_i64) : Nil
# Why the last call failed, in Windows' own words. A message that names
# only what was attempted — "Cannot symlink A to B" — leaves the caller
# with nothing to act on, and on Windows the difference between "a
# required privilege is not held" and "the file already exists" is the
# difference between a machine setting and a bug in the program. The
# code is kept beside the text because the text is localised and the
# number is not.
#
# FORMAT_MESSAGE_FROM_SYSTEM is 0x1000 and FORMAT_MESSAGE_IGNORE_INSERTS
# 0x200: without the second, a message with an insert in it fails rather
# than printing the placeholder. Windows ends these sentences with CRLF
# and sometimes a trailing space, which is a line break in the middle of
# a panic, so the tail comes off. `std/dir`'s refusals say it too.
def self.win_error : String
def self.writable?(path : String | Path) : Bool
endFile::Flagsstruct, reopened
struct ::File::Flags
def initialize(value : Int32 = 0)
def set_group? : Bool
def set_user? : Bool
def sticky? : Bool
def value : Int32
endFile::Infostruct, reopened
struct ::File::Info
def dev : Int64
def directory? : Bool
def executable? : Bool
def file? : Bool
def flags : Flags
def group_id : String
def initialize(size : Int64, permissions : Permissions, type : Type, flags : Flags, modification_time : Int64, owner_id : String, group_id : String, dev : Int64 = 0_i64, ino : UInt64 = 0_u64)
def ino : UInt64
def modification_time : Int64
def owner_id : String
def permissions : Permissions
def readable? : Bool
# An identity of 0 is none: Windows answers a path it could not open
# with the attributes alone (`info?`), and two such files - different
# sizes, different contents - were the same file.
def same_file?(other : Info) : Bool
def size : Int64
def symlink? : Bool
def type : Type
def writable? : Bool
endFile::Permissionsstruct, reopened
struct ::File::Permissions
def group_execute? : Bool
def group_read? : Bool
def group_write? : Bool
def initialize(value : Int32)
def other_execute? : Bool
def other_read? : Bool
def other_write? : Bool
def owner_execute? : Bool
def owner_read? : Bool
def owner_write? : Bool
def to_i : Int32
def to_s(io : IO) : Nil
def to_s : String
def value : Int32
endFile::Typeenum, reopened
enum ::File::Type : UInt8
# Returns `true` if this enum value equals `BlockDevice`
def block_device? : Bool
# Returns `true` if this enum value equals `CharacterDevice`
def character_device? : Bool
def device? : Bool
# Returns `true` if this enum value equals `Directory`
def directory? : Bool
# Returns `true` if this enum value equals `File`
def file? : Bool
# Returns `true` if this enum value equals `Pipe`
def pipe? : Bool
# Returns `true` if this enum value equals `Socket`
def socket? : Bool
# Returns `true` if this enum value equals `Symlink`
def symlink? : Bool
endIyiIOclass, reopened
class ::IyiIO
# Advisory locks on the whole file, the other library's `flock_*`: a
# shared one many holders may have at once, an exclusive one a single
# holder. The holder is this open file - another `File.open` of the same
# path, in this process or another, is another holder - until
# `flock_unlock`, or until the file is closed.
#
# File.open("app.lock", "w") do |f|
# f.flock_exclusive { run_alone }.or_panic
# end
#
# A lock another holder has is waited for a task at a time: tried again
# after 1, 2, 4 ... 64 ms, the thread's other tasks running meanwhile,
# and cancellable. `try_flock_*` answers at once whether it took it.
#
# Linux and darwin lock with `flock(2)`, which only other locks heed, and
# turn a shared lock this file holds into an exclusive one in place.
# Windows locks every byte with `LockFileEx`, which is mandatory - while
# one handle holds it exclusively, another handle's reads and writes of
# the file fail - and counts each lock a handle takes: unlock a shared
# lock before taking the exclusive one.
def flock_exclusive : Nil | Cancelled
# The block's answer, run with the lock held and unlocked after it, even
# when the block panics.
def flock_exclusive(&block : (-> R)) : R | Cancelled forall R
def flock_shared : Nil | Cancelled
def flock_shared(&block : (-> R)) : R | Cancelled forall R
# Gives the lock back; one this file does not hold is no error.
def flock_unlock : Nil
# The kernel's move: the new offset, or a negative error. A stream with
# no descriptor - a `Memory` - is -1, which Windows' `to_u64` of it
# panicked "arithmetic overflow" on; it is EBADF everywhere, as Linux's
# kernel answers it.
protected def self.lseek(fd : Int64, offset : Int64, whence : Int32) : Int64
# Bytes from the start to where the next read or write happens.
def pos : Int64
def pos=(position : Int64) : Int64
# Moves to *offset* from the start, from here, or from the end, and
# answers the new position.
def seek(offset : Int64, whence : Seek = Seek::Set) : Int64
def seek(offset : Int32, whence : Seek = Seek::Set) : Int64
def try_flock_exclusive : Bool
def try_flock_shared : Bool
endIyiIO::Seekenum, reopened
enum ::IyiIO::Seek : Int32
end
File: comprehensive file operations, metadata inspection, and manipulation.