Shell API¶
Basic operations¶
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
The write functions are atomic (write to a temp file and then move into place, deleting on failure).
Recursive operations¶
By default operations are recursive and create parent directories.
1 2 3 4 5 | |
cp and mv have more useful behavior than the UNIX equivalents.
1 2 | |
cp¶
- Overlays. If
sourceis a directory anddestis a pre-existing directory, the contents of source are recursively copied intodest, replacing whatever was there. That is,source/foois copied todestination/foonotdestination/source/fooas you may expect given the behaviour of the UNIXcpcommand. If you want that behaviour specify the destination as a subdirectory with the same name assourcee.g.cp("src", "dest/src"). - File to directory. If
sourceis a file anddestis a pre-existing directory, it is copied into that directory with the same name, overwriting any file with the same name that's already there. - Creates directories. If
sourceis a file anddestdoes not exist, destination is treated as a file and the directory it's in is created along with all parents. - File overwrites. If
sourceis a file anddestis a file in a pre-existing directory, it is copied to that given path exactly, replacing the file. - If
sourceis a directory anddestis a pre-existing file,IllegalStateExceptionis thrown.
mv¶
mv moves from to to, overwriting or merging with to if it exists.
This command has subtly different semantics to the shell mv command or Files.move. It allows you to move a directory 'over'
another directory without throwing a DirectoryNotEmptyException. If to is a directory and isn't empty, then instead of it
being moved into that directory with the same name, each file is moved individually with directories being created as necessary
in the destination, giving a form of merge semantics. If you want to move a directory to a subdirectory of somewhere else, you
should therefore re-specify the source directory name as the last component of the target path.
However, if you try to move a file to a directory then it will be moved into that directory with the same name.
Warning
Currently extended attributes won't be copied when doing a merge, nor is the move atomic.
Non-destructive moves¶
Moves this file to the given path, but if a file with the same name already exists there the move will be to a file named name
(1).extension, name (2).extension, etc.
1 2 3 4 | |
Changing directory and temp dirs¶
- Changing to a non-existent directory will create it.
cdcan take a code block which changes the workingdironly for the duration of that block.mktmpreturns a temp directory that will be recursively deleted when the script terminates.
1 2 3 4 5 6 7 8 9 10 11 | |

Hashing files and directories¶
Secure (slow, large) and insecure (fast, small) hash functions are supported. You can hash a directory tree (see below for details) which is useful to determine if a tree has changed. Hashing a directory tree occurs in parallel: both files and sub-blocks of files will be hashed across multiple CPU cores, so the process is fast. When hashing a tree symlinks aren't followed, instead their target is included into the hash. Progress events are generated automatically.
1 2 | |
The "fingerprint" hash function (in the FINGERPRINT global constant) is a Merkleized variant of xxhash64 that enables parallel hashing.
There is also "fingerprint-metadata" (FINGERPRINT_METADATA) that doesn't hash contents, only file name, mtime and other filesystem
metadata.
What's actually hashed when hashing a directory tree is implementation defined, however in the current code it's actually a hash of the string containing a Unicode-art tree annotated with metadata and fingerprints.
A common use case for this is determining if files or directories have changed. The mark function hashes a file or directory tree and then
stores the result in an extended attribute (alternative file stream on Windows). You can then use modifiedSinceMark to determine if there
was any change since the mark was placed (and optionally, to update the mark at the same time). Using extended attributes ensures that
the up-to-date check works even if the user moves the directory being observed.
Permissions¶
On Windows UNIX permissions are mapped to the closest equivalent and then stored in an extended attribute, ensuring that if you create an archive the permissions you set will be preserved on UNIX, even though they didn't make sense on Windows.
chmod can take both deltas to permissions as above, or rw-r--r-- style permission sets.
1 2 3 4 5 6 7 8 9 10 11 12 | |
Archives¶
1 2 3 4 5 6 7 8 | |
The tar function also supports tar.bz2, tar.xz and tar.Z. Compression level can be controlled via zipOptions.compressionLevel. Single
files can also be archived, and will be placed in the root.
Finding things¶
1 2 3 4 5 | |
Disk usage¶
1 2 | |
Accounting of hard links can be controlled.
Extended attributes¶
Also works on Windows.
1 2 3 | |
Open in a GUI app¶
1 2 | |
Environment variables¶
1 2 | |
Directory trees¶
tree emits Unicode-art directory trees:
1 2 3 4 | |
... yields ...
1 2 3 4 | |
You can annotate each item in the tree and trees can be colored:
1 2 | |

Beyond debugging the primary use for this is verifying directory trees match what you expect, or quickly checking if a directory has changed. See hashing files and directories for more information.
You can combineAnnotators if you want more than one, or define your own Shell.TreeAnnotator object.
Path.subTree(relative: Boolean) returns a sorted list of all paths under that path, excluding that path.
Encoding things¶
1 2 3 | |
Diffing things¶
1 2 3 4 5 6 | |
Editing text files¶
edit locks and opens a text file for editing, providing a mutable StringBuilder within the lambda block. It's assumed the text file is in
the system encoding, and that it is less than 2GB in size. If the file doesn't exist, it is created.
1 2 3 | |
Similar to edit and implemented using it, sed will update the given text file in place, replacing any matches of the given regex with the
result of calling a lambda. This is a convenient utility for editing text files when the operation can be expressed as a transformation
over a regular expression match.
1 2 3 | |
Please note that despite sed originally being short for "stream editor", this function loads the whole file into memory rather than doing a streaming match. It also doesn't support the same feature set as the real sed.
The regular expression will be used in multi-line mode. If you don't want that then you should use the overload that lets you give a regex object.