(1.1K lines)
4 Gets the file access time of a file.8 A 64-bit unix epoch timestamp representing when the file or directory was last9 accessed, or `none` if no such file or directory exists.14 The path of the file whose access time you want.19 Whether to follow symbolic links.21 assert (./file.txt).accessed() == Int64(1704221100)22 assert (./not-a-file).accessed() == none27 Appends the given text to the file at the specified path, creating the file if28 it doesn't already exist. Failure to write will result in a runtime error.32 Either `Success` or `Failure(reason)`.37 The path of the file to append to.41 The text to append to the file.46 The permissions to set on the file if it is being created.48 (./log.txt).append("extra line\n")!53 Appends the given bytes to the file at the specified path, creating the file if54 it doesn't already exist. Failure to write will result in a runtime error.58 Either `Success` or `Failure(reason)`.63 The path of the file to append to.67 The bytes to append to the file.72 The permissions to set on the file if it is being created.74 (./log.txt).append_bytes([104, 105])!79 Returns the base name of the file or directory at the specified path.83 The base name of the file or directory.88 The path of the file or directory.90 assert (./path/to/file.txt).base_name() == "file.txt"95 Returns an iterator that can be used to iterate over a file one line at a time,96 or returns none if the file could not be opened.100 An iterator that can be used to get lines from a file one at a time or101 none if the file couldn't be read.106 The path of the file.108 # Safely handle file not being readable:109 if lines := (./file.txt).by_line()110 for line in lines111 say(line.upper())112 else113 say("Couldn't read file!")115 # Assume the file is readable and error if that's not the case:116 for line in (/dev/stdin).by_line()!117 say(line.upper())122 Returns a list with the lines of text in a file or returns none if the file123 could not be opened.127 A list of the lines in a file or none if the file couldn't be read.132 The path of the file.134 lines := (./file.txt).lines()!139 Returns whether or not a file can be executed by the current user/group.143 `yes` if the file or directory exists and the current user has execute permissions, otherwise `no`.148 The path of the file to check.150 assert (/bin/sh).can_execute() == yes151 assert (/usr/include/stdlib.h).can_execute() == no152 assert (/non/existant/file).can_execute() == no157 Returns whether or not a file can be read by the current user/group.161 `yes` if the file or directory exists and the current user has read permissions, otherwise `no`.166 The path of the file to check.168 assert (/usr/include/stdlib.h).can_read() == yes169 assert (/etc/shadow).can_read() == no170 assert (/non/existant/file).can_read() == no175 Returns whether or not a file can be written by the current user/group.179 `yes` if the file or directory exists and the current user has write permissions, otherwise `no`.184 The path of the file to check.186 assert (/tmp).can_write() == yes187 assert (/etc/passwd).can_write() == no188 assert (/non/existant/file).can_write() == no193 Gets the file change time of a file.195 This is the ["ctime"](https://en.wikipedia.org/wiki/Stat_(system_call)#ctime) of a file,196 which is _not_ the file creation time.200 A 64-bit unix epoch timestamp representing when the file or directory was last201 changed, or `none` if no such file or directory exists.206 The path of the file whose change time you want.211 Whether to follow symbolic links.213 assert (./file.txt).changed() == Int64(1704221100)214 assert (./not-a-file).changed() == none219 Return a path that is a child of another path.223 A new path representing the child.228 The path of a directory.232 The name of a child file or directory.234 assert (./directory).child("file.txt") == (./directory/file.txt)239 Returns a list of children (files and directories) within the directory at240 the specified path. Optionally includes hidden files. Child ordering is not241 specified.245 A list of paths for the children.250 The path of the directory.254 Whether to include hidden files (those starting with a `.`).256 assert (./directory).children(include_hidden=yes) == [(./directory/.git), (./directory/foo.txt)]261 Creates a new directory at the specified path with the given permissions. If262 any of the parent directories do not exist, they will be created as needed.264 return:265 type: 'Result'266 description: >267 Either `Success` or `Failure(reason)`.268 args:269 path:270 type: 'Path'271 description: >272 The path of the directory to create.273 permissions:274 default: 'Int32(0o755)'275 description: >276 The permissions to set on the new directory.277 recursive:278 default: 'yes'279 description: >280 If set to `yes`, then recursively create any parent directories if they281 don't exist, otherwise fail if the parent directory does not exist. When282 set to `yes`, this function behaves like `mkdir -p`.283 example: |284 (./new_directory).create_directory()!289 Creates a new directory at the specified path with the given permissions. If290 any of the parent directories do not exist, they will be created as needed.294 The absolute path of the current directory.297 assert Path.current_dir() == (/home/user/tomo)302 Returns an iterator over the children (files and directories) within the303 directory at the specified path. Optionally includes hidden files.304 Iteration order is not specified.308 An iterator over the children in a directory or `none` if the path is not309 a directory or a symlink to a directory.314 The path of the directory.318 Whether to include hidden files (those starting with a `.`).320 for child in (/dir).each_child()321 say("Child: $child")326 Checks if a file or directory exists at the specified path.330 `True` if the file or directory exists, `False` otherwise.335 The path to check.337 assert (/).exists() == yes342 For home-based paths (those starting with `~`), expand the path to replace the343 tilde with and absolute path to the user's `$HOME` directory.347 If the path does not start with a `~`, then return it unmodified. Otherwise,348 replace the `~` with an absolute path to the user's home directory.353 The path to expand.355 # Assume current user is 'user'356 assert (~/foo).expand_home() == (/home/user/foo)357 # No change358 assert (/foo).expand_home() == (/foo)363 Returns the file extension of the file at the specified path. Optionally returns the full extension.367 The file extension (not including the leading `.`) or an empty text if there is368 no file extension.373 The path of the file.378 Whether to return everything after the first `.` in the base name, or379 only the last part of the extension.381 assert (./file.tar.gz).extension() == "tar.gz"382 assert (./file.tar.gz).extension(full=no) == "gz"383 assert (/foo).extension() == ""384 assert (./.git).extension() == ""389 Returns a list of files within the directory at the specified path. Optionally includes hidden files.393 A list of file paths.398 The path of the directory.403 Whether to include hidden files (those starting with a `.`).405 assert (./directory).files(include_hidden=yes) == [(./directory/file1.txt), (./directory/file2.txt)]410 Perform a globbing operation and return a list of matching paths. Some glob411 specific details:413 - The paths "." and ".." are *not* included in any globbing results.415 - Files or directories that begin with "." will not match `*`, but will match `.*`.417 - Globs do support `{a,b}` syntax for matching files that match any of several418 choices of patterns.420 - The shell-style syntax `**` for matching subdirectories is not supported.424 A list of file paths that match the glob.429 The path of the directory which may contain special globbing characters430 like `*`, `?`, or `{...}`432 # Current directory includes: foo.txt, baz.txt, qux.jpg, .hidden433 assert (./*).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]434 assert (./*.txt).glob() == [(./foo.txt), (./baz.txt)]435 assert (./*.{txt,jpg}).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]436 assert (./.*).glob() == [(./.hidden)]438 # Globs with no matches return an empty list:439 assert (./*.xxx).glob() == []444 Get the owning group of a file or directory.448 The name of the group which owns the file or directory, or `none` if the path does not exist.453 The path whose owning group to get.458 Whether to follow symbolic links.460 assert (/bin).group() == "root"461 assert (/non/existent/file).group() == none466 Return whether or not a path has a given file extension.470 Whether or not the path has the given extension.475 A path.479 A file extension (leading `.` is optional). If empty, the check will480 test if the file does not have any file extension.482 assert (/foo.txt).has_extension("txt") == yes483 assert (/foo.txt).has_extension(".txt") == yes484 assert (/foo.tar.gz).has_extension("gz") == yes485 assert (/foo.tar.gz).has_extension("zip") == no490 Checks if the path represents a directory. Optionally follows symbolic links.494 `True` if the path is a directory, `False` otherwise.499 The path to check.503 Whether to follow symbolic links.505 assert (./directory/).is_directory() == yes506 assert (./file.txt).is_directory() == no511 Checks if the path represents a file. Optionally follows symbolic links.515 `True` if the path is a file, `False` otherwise.520 The path to check.524 Whether to follow symbolic links.526 assert (./file.txt).is_file() == yes527 assert (./directory/).is_file() == no532 Checks if the path represents a socket. Optionally follows symbolic links.536 `True` if the path is a socket, `False` otherwise.541 The path to check.545 Whether to follow symbolic links.547 assert (./socket).is_socket() == yes552 Checks if the path represents a symbolic link.556 `True` if the path is a symbolic link, `False` otherwise.561 The path to check.563 assert (./link).is_symlink() == yes568 Return whether or not a path matches a given glob.572 Whether or not the path matches the given glob.577 The path to check.581 The glob pattern to check.583 assert (./file.txt).matches_glob("*.txt")584 assert (./file.c).matches_glob("*.{c,h}")589 Gets the file modification time of a file.593 A 64-bit unix epoch timestamp representing when the file or directory was last594 modified, or `none` if no such file or directory exists.599 The path of the file whose modification time you want.604 Whether to follow symbolic links.606 assert (./file.txt).modified() == Int64(1704221100)607 assert (./not-a-file).modified() == none612 Moves the file or directory from one location to another.616 Either `Success` or `Failure(reason)`.621 The path to move.625 The destination to move the path to.629 Whether to permit overwriting the destination if it is an existing file or directory.631 (./file.txt).move(/tmp/renamed.txt)!636 Get the owning user of a file or directory.640 The name of the user who owns the file or directory, or `none` if the path does not exist.645 The path whose owner to get.650 Whether to follow symbolic links.652 assert (/bin).owner() == "root"653 assert (/non/existent/file).owner() == none658 Returns the parent directory of the file or directory at the specified path.662 The path of the parent directory or `none` if the path is `(/)` (the file root).667 The path of the file or directory.669 assert (./path/to/file.txt).parent() == (./path/to/)674 Reads the contents of the file at the specified path or none if the file675 could not be read.679 The contents of the file. If the file could not be read, none will be680 returned. If the file can be read, but is not valid UTF8 data, an error681 will be raised.686 The path of the file to read.688 assert (./hello.txt).read() == "Hello"689 assert (./nosuchfile.xxx).read() == none694 Reads the contents of the file at the specified path or none if the file695 could not be read.699 The byte contents of the file. If the file cannot be read, none will be700 returned.705 The path of the file to read.710 A limit to how many bytes should be read.712 assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]713 assert (./nosuchfile.xxx).read_bytes() == none718 Returns the path relative to a given base path. By default, the base path is the current directory.722 A relative path from the reference point to the given path.727 The path to convert.731 The base path for the relative path.733 assert (./path/to/file.txt).relative_to((./path)) == (./to/file.txt)734 assert (/tmp/foo).relative_to((/tmp)) == (./foo)739 Removes the file or directory at the specified path. A runtime error is raised if something goes wrong.743 Either `Success` or `Failure(reason)`.748 The path to remove.752 Whether to ignore errors if the file or directory does not exist.754 (./file.txt).remove()!759 Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory.763 The resolved absolute path.768 The path to resolve.772 The base path for resolution.774 assert (~/foo).resolved() == (/home/user/foo)775 assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)780 Set the owning user and/or group for a path.784 Either `Success` or `Failure(reason)`.789 The path to change the permissions for.794 If non-none, the new user to assign to be the owner of the file.799 If non-none, the new group to assign to be the owner of the file.804 Whether to follow symbolic links.806 (./file.txt).set_owner(owner="root", group="wheel")!811 Return a path that is a sibling of another path (i.e. has the same parent,812 but a different name). This is equivalent to `.parent().child(name)`816 A new path representing the sibling.821 A path.825 The name of a sibling file or directory.827 assert (/foo/baz).sibling("doop") == (/foo/doop)832 Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.836 A list of subdirectory paths.841 The path of the directory.845 Whether to include hidden subdirectories (those starting with a `.`)847 assert (./directory).subdirectories() == [(./directory/subdir1), (./directory/subdir2)]848 assert (./directory).subdirectories(include_hidden=yes) == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]853 Generates a unique directory path based on the given path. Useful for creating temporary directories.857 A unique directory path after creating the directory.862 The base path for generating the unique directory. The last six letters of this path must be `XXXXXX`.864 created := (/tmp/my-dir.XXXXXX).unique_directory()865 assert created.is_directory() == yes866 created.remove()!871 Returns an iterator that efficiently recursively walks over every file and872 subdirectory in a given directory. The iteration order is not defined, but873 in practice it may look a lot like a breadth-first traversal.875 The path itself is always included in the iteration.879 An iterator that recursively walks over every file and subdirectory.884 The path to begin the walk.888 Whether to include hidden files (those starting with a `.`)893 Whether to follow symbolic links. Caution: if set to 'yes', it is894 possible for this iterator to get stuck in a loop, using increasingly895 large amounts of memory.897 for p in (/tmp).walk()898 say("File or dir: $p")900 # The path itself is always included:901 assert [p for p in (./file.txt).walk()] == [(./file.txt)]906 Writes the given text to the file at the specified path, creating the file if907 it doesn't already exist. Sets the file permissions as specified. If the file908 writing cannot be successfully completed, a runtime error is raised.912 Either `Success` or `Failure(reason)`.917 The path of the file to write to.921 The text to write to the file.925 The permissions to set on the file if it is created.927 (./file.txt).write("Hello, world!")!932 Returns a function that can be used to repeatedly write to the same file.934 The file writer will keep its file descriptor open after each write (unless935 the `close` argument is set to `yes`). If the file writer is never closed,936 it will be automatically closed when the file writer is garbage collected.940 Returns a function that can repeatedly write to the same file. If `close`941 is set to `yes`, then the file will be closed after writing. If this942 function is called again after closing, the file will be reopened for943 appending.948 The path of the file to write to.953 If set to `yes`, writes to the file will append. If set to `no`, then954 the first write to the file will overwrite its contents and subsequent955 calls will append.960 The permissions to set on the file if it is created.962 write := (./file.txt).writer()963 write("Hello\n")!964 write("world\n", close=yes)!969 Returns a function that can be used to repeatedly write bytes to the same970 file.972 The file writer will keep its file descriptor open after each write (unless973 the `close` argument is set to `yes`). If the file writer is never closed,974 it will be automatically closed when the file writer is garbage collected.978 Returns a function that can repeatedly write bytes to the same file. If979 `close` is set to `yes`, then the file will be closed after writing. If980 this function is called again after closing, the file will be reopened981 for appending.986 The path of the file to write to.991 If set to `yes`, writes to the file will append. If set to `no`, then992 the first write to the file will overwrite its contents and subsequent993 calls will append.998 The permissions to set on the file if it is created.1000 write := (./file.txt).byte_writer()1001 write("Hello\n".utf8())!1002 write("world\n".utf8(), close=yes)!1008 Writes the given bytes to the file at the specified path, creating the file if1009 it doesn't already exist. Sets the file permissions as specified. If the file1010 writing cannot be successfully completed, a runtime error is raised.1014 Either `Success` or `Failure(reason)`.1019 The path of the file to write to.1023 A list of bytes to write to the file.1027 The permissions to set on the file if it is created.1029 (./file.txt).write_bytes([104, 105])!1034 Writes the given text to a unique file path based on the specified path. The1035 file is created if it doesn't exist. This is useful for creating temporary1036 files.1040 The path of the newly created unique file.1045 The base path for generating the unique file. This path must include1046 the string `XXXXXX` in the file base name.1050 The text to write to the file.1052 created := (./file-XXXXXX.txt).write_unique("Hello, world!")!1053 assert created == (./file-27QHtq.txt)1054 assert created.read()! == "Hello, world!"1055 created.remove()!1060 Writes the given bytes to a unique file path based on the specified path. The1061 file is created if it doesn't exist. This is useful for creating temporary1062 files.1066 The path of the newly created unique file.1071 The base path for generating the unique file. This path must include1072 the string `XXXXXX` in the file base name.1076 The bytes to write to the file.1078 created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!1079 assert created == (./file-27QHtq.txt)1080 assert created.read_bytes()! == [1, 2, 3]1081 created.remove()!