https://github.com/babashka/fs
File system utility library for Clojure
https://github.com/babashka/fs
clojure java-nio
Last synced: 9 days ago
JSON representation
File system utility library for Clojure
- Host: GitHub
- URL: https://github.com/babashka/fs
- Owner: babashka
- License: epl-1.0
- Created: 2020-11-16T09:30:24.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2025-06-07T12:31:58.000Z (8 months ago)
- Last Synced: 2025-06-08T22:13:45.265Z (8 months ago)
- Topics: clojure, java-nio
- Language: Clojure
- Homepage:
- Size: 398 KB
- Stars: 186
- Watchers: 5
- Forks: 46
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# babashka.fs
[](https://clojars.org/babashka/fs) [](https://github.com/babashka/fs/actions/workflows/ci.yml)
[](https://book.babashka.org#badges)
File system utilities. This library can used from:
- [Clojure on the JVM](https://www.clojure.org/guides/install_clojure) - we support Clojure 1.10.3 and above on Java 11 and above.
- [babashka](https://github.com/babashka/babashka) - it has been a built-in library since babashka v0.2.9.
## Why
Babashka is a scripting utility. It's convenient to have cross platform file
system utilities available for scripting. The namespace `clojure.java.io`
already offers a bunch of useful features, but it predates `java.nio`. The nio
package isn't that nice to use from Clojure and this library should help with
that.
The main inspirations for this library are
[clojure.java.io](https://clojure.github.io/clojure/clojure.java.io-api.html),
[clj-commons/fs](https://github.com/clj-commons/fs) and
[corasaurus-hex/fs](https://github.com/corasaurus-hex/fs/blob/master/src/corasaurus_hex/fs.clj).
## API docs
See [API.md](API.md).
## Usage
``` clojure
(require '[babashka.fs :as fs])
(fs/directory? ".") ;;=> true
```
## Examples
The `glob` function takes a root path and a pattern. The pattern is interpreted
as documented
[here](https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)).
``` clojure
(map str (fs/glob "." "**{.clj,cljc}"))
```
Output:
``` clojure
("project.clj" "test/babashka/fs_test.clj" "src/babashka/fs.cljc")
```
The function `exec-paths` returns all entries from `PATH` as `Path`s. To search
all these directories for an executable, e.g. `java`, you can combine it with
`list-dirs` which searches files directly in the directories using an (optional)
glob pattern:
``` clojure
(str (first (filter fs/executable? (fs/list-dirs (filter fs/exists? (fs/exec-paths)) "java"))))
"/Users/borkdude/.jenv/versions/11.0/bin/java"
```
For convenience, the above use case is also supported using the `which` function:
``` clojure
(str (fs/which "java"))
"/Users/borkdude/.jenv/versions/11.0/bin/java"
```
## Notes
### File Systems & OSes
Behaviour can vary on different file systems and OSes.
If you uncover some interesting nuance, please let us know.
### Empty String Paths
The underlying JDK file APIs (and, by extension, babashka.fs) typically consider an empty-string path `""` to be the current working directory. This means that `(fs/list-dir "")` is functionally equivalent to `(fs/list-dir ".")`.
### creation-time
Depending on which OS and JDK version you are running, `creation-time` might return unexpected results.
As of this writing, our testing has revealed:
- Windows - returns creation time as expected
- macOS
- after Java 17 returns creation time as expected
- otherwise returns modified time
- Linux
- before Java 17 returns modified time
- otherwise returns creation time
See [JDK-8316304](https://bugs.openjdk.org/browse/JDK-8316304).
### set-creation-time
Depending on which OS and JDK version you are running, `set-creation-time` might not do what you would expect.
As of this writing, our testing has revealed:
- Windows - sets creation time as expected
- macOS
- after Java 17 sets creation time as expected
- otherwise has no effect
- Linux - seems to have no effect
See [JDK-8151430](https://bugs.openjdk.org/browse/JDK-8151430)
### :nofollow-links
Many babashka.fs functions accept the `:nofollow-links` option.
These functions will follow symbolic links unless you pass in `{:nofollow-links true}`.
### :follow-links
Some babashka.fs functions accept the `:follow-links` option.
These functions will _not_ follow symbolic links unless you pass in `{:follow-links true}`.
## Test & Dev
To run all tests
```
$ bb test
```
You can also use [cognitect test-runner](https://github.com/cognitect-labs/test-runner?tab=readme-ov-file#invoke-with-clojure--m-clojuremain) options, for example, to run a single test:
```
bb test --var babashka.fs-test/walk-test
```
> [!NOTE]
> To allow us to contrive isolated file system scenarios, tests are always run from the scratch current working directory `./target/test-cwd`.
To fire up a REPL when working on these tests, run:
```
bb dev
```
> [!TIP]
> The `.nrepl-port` file will be generated under `./target/test-cwd/`, so you'll have to type the REPL port in manually when connecting.
### API Docs
This project generates API docs with quickdoc, to regenerate `API.md`:
```
shell quickdoc
```
## License
Copyright © 2020-2025 Michiel Borkent
Distributed under the EPL License, same as Clojure. See LICENSE.