list(), walk(), and sizeRecursively() work on folders from the directory picker, and the experimental origin private file system adds listEntries() and delete(). Call the other functions from nonWebMain or a platform source set.
Usage
nonWebMain
Options
Int
default:"Int.MAX_VALUE"
walk
1 yields only the direct children. Must be positive.Boolean
default:"false"
createDirectories
true throws if the directory already exists.Boolean
default:"false"
copyRecursively
true replaces existing files. See Copy a directory tree.Boolean
default:"true"
delete
true throws if the file doesn’t exist.Boolean
default:"false"
delete
true empties a directory before removing it.List a directory
list() returns the direct children and throws on a regular file. It does blocking I/O: on every platform except the web, call it on Dispatchers.IO.
Walk a directory tree
walk() lazily yields every file and subdirectory below a directory, depth-first, without the directory itself:
walk() yields only that file. It is synchronous, like list(): iterate it on Dispatchers.IO.
Get the size of a tree
sizeRecursively() adds up the size of every regular file in the tree, or returns the file’s own size for a regular file. Files whose size is unknown count as 0. It is a suspend function that switches to Dispatchers.IO on every platform except the web.
Symbolic links are never followed by walk() or sizeRecursively(), so a link can’t cause an infinite loop: walk() yields the link itself, and sizeRecursively() counts it as 0. This also applies when you call them on a link.
Create directories
nonWebMain
createDirectories() creates the directory and any missing parent. It does nothing if the directory already exists, unless you pass mustCreate = true.
Copy a file
nonWebMain
copyTo() streams the content, so it works when the source size is unknown. An existing destination file is replaced. It throws if the source and destination are the same file, or if the destination folder contains a directory with the source’s name.
Copy a directory tree
copyRecursively() copies a file or a whole directory tree. Unlike copyTo(), the target becomes the new root, not a folder to copy into (as with Kotlin’s File.copyRecursively()):
nonWebMain
- The copy stops at the first error and leaves the target partially copied: there is no rollback.
- Symbolic links inside the tree are skipped. Calling it on a link, or copying a directory into itself, throws.
- It runs on
Dispatchers.IO.
Move a file
nonWebMain
atomicMove() renames the file in a single step and replaces an existing destination file. When the destination is an existing directory, the file moves into it under its own name. Moving across volumes can throw UnsupportedOperationException: use copyTo() then delete() instead.
Delete a file or directory
nonWebMain
recursively = true, deleting a non-empty directory throws. Symbolic links (including dangling links) and Windows directory junctions are removed as links: their targets are left untouched.
Platform notes
Android: content:// files and document trees
Android: content:// files and document trees
atomicMove()falls back to copy then delete when the source or the destination is acontent://file, and doesn’t support directories.delete()lets the document provider remove the document, with its contents, whateverrecursivelysays.list(),walk(), andsizeRecursively()cost provider queries for each subdirectory, so large trees are slow. Files whose provider doesn’t report a size count as0.copyRecursively()accepts document trees as a source. As a target, it can create subdirectories only with providers whose document IDs are paths, such as device storage: with other providers, it throws when it needs a new subdirectory. An entry named.or.., containing/, or sharing its name with a sibling makes the copy throw before anything is written. Copying a tree into itself is detected only for providers whose document IDs are paths.
iOS and macOS: security-scoped folders
iOS and macOS: security-scoped folders
Keep security-scoped access to a picked folder active while you iterate
walk(), for example inside folder.withScopedAccess { }. copyRecursively() holds access to the source and the target for the whole copy.Windows: reparse points
Windows: reparse points
Every reparse point counts as a link, including directory junctions and OneDrive Files On-Demand folders.
walk() lists such a folder without its contents, sizeRecursively() doesn’t count it, and copyRecursively() skips it. A copyRecursively() target that reaches the source through a junction isn’t detected as being inside it: the copy doesn’t throw, and it still ends without copying its own output.Web: picked folders only
Web: picked folders only
list(), walk(), and sizeRecursively() work on folders returned by the directory picker, whose tree is already in memory, and run on the caller’s dispatcher. They throw on origin private file system directories: use listEntries() instead. copyTo(), copyRecursively(), createDirectories(), and atomicMove() are not available. delete() exists only for origin private file system entries. See Files on the web.Related
- PlatformFile: paths, properties, and the
/operator - Writing files
- Directory picker: let the user pick a folder