babashka.fs
A guide to using babashka.fs.
What this skill does
# Babashka.fs File System Utilities Skill
## Overview
The `babashka.fs` library is a comprehensive file system utility library for Clojure, designed for cross-platform file operations. It provides a clean, functional API for working with files, directories, and paths, built on top of Java's NIO.2 API while offering a more idiomatic Clojure interface.
**When to use this skill:**
- When working with files and directories in Clojure/Babashka scripts
- When you need cross-platform file system operations
- When writing build tasks, file processing scripts, or automation tools
- When you need to search, filter, or manipulate file systems programmatically
## Setup and Requirements
### Adding to your project
```clojure
;; In deps.edn
{:deps {babashka/fs {:mvn/version "0.5.27"}}}
;; In your namespace
(ns my-script
(:require [babashka.fs :as fs]))
```
### Built-in to Babashka
The library is built into Babashka, so no additional dependencies are needed for bb scripts:
```clojure
#!/usr/bin/env bb
(require '[babashka.fs :as fs])
(fs/directory? ".") ; => true
```
## Core Concepts
### Path Objects
Most functions accept and return `java.nio.file.Path` objects, but also work with strings and other path-like objects. The library automatically coerces between types.
```clojure
;; All of these work
(fs/exists? ".")
(fs/exists? (fs/path "."))
(fs/exists? (java.io.File. "."))
```
### Cross-Platform Support
The library handles platform differences automatically, but provides utilities when you need platform-specific behavior:
```clojure
;; Works on all platforms
(fs/path "dir" "subdir" "file.txt")
;; Convert to Unix-style paths (useful for Windows)
(fs/unixify "C:\\Users\\name\\file.txt") ; => "C:/Users/name/file.txt"
```
## Path Operations
### Creating and Manipulating Paths
```clojure
;; Create paths
(fs/path "dir" "subdir" "file.txt") ; Join path components
(fs/file "dir" "subdir" "file.txt") ; Alias for fs/path
;; Path properties
(fs/absolute? "/tmp/file.txt") ; true
(fs/relative? "dir/file.txt") ; true
(fs/hidden? ".hidden-file") ; Check if hidden
;; Path transformations
(fs/absolutize "relative/path") ; Convert to absolute
(fs/canonicalize "/tmp/../file.txt") ; Resolve to canonical form
(fs/normalize "/tmp/./dir/../file.txt") ; Normalize path
;; Path components
(fs/file-name "/path/to/file.txt") ; "file.txt"
(fs/parent "/path/to/file.txt") ; "/path/to"
(fs/extension "file.txt") ; "txt"
(fs/split-ext "file.txt") ; ["file" "txt"]
(fs/strip-ext "file.txt") ; "file"
;; Path relationships
(fs/starts-with? "/foo/bar" "/foo") ; true
(fs/ends-with? "/foo/bar.txt" "bar.txt") ; true
(fs/relativize "/foo/bar" "/foo/bar/baz") ; "baz"
;; Get all components
(fs/components "/path/to/file.txt") ; Seq of path components
```
### Working with Extensions
```clojure
;; Get extension
(fs/extension "document.pdf") ; "pdf"
(fs/extension "archive.tar.gz") ; "gz"
;; Split filename and extension
(fs/split-ext "document.pdf") ; ["document" "pdf"]
;; Remove extension
(fs/strip-ext "document.pdf") ; "document"
(fs/strip-ext "archive.tar.gz") ; "archive.tar"
```
## File and Directory Checks
```clojure
;; Existence and type checks
(fs/exists? "file.txt") ; Does it exist?
(fs/directory? "path/to/dir") ; Is it a directory?
(fs/regular-file? "file.txt") ; Is it a regular file?
(fs/sym-link? "link") ; Is it a symbolic link?
(fs/hidden? ".hidden") ; Is it hidden?
;; Permission checks
(fs/readable? "file.txt") ; Can we read it?
(fs/writable? "file.txt") ; Can we write to it?
(fs/executable? "script.sh") ; Can we execute it?
;; Comparison
(fs/same-file? "file1.txt" "file2.txt") ; Are they the same file?
```
## Creating Files and Directories
```clojure
;; Create directories
(fs/create-dir "new-dir") ; Create single directory
(fs/create-dirs "path/to/new/dir") ; Create with parents
;; Create files
(fs/create-file "new-file.txt") ; Create empty file
;; Create temporary files/directories
(fs/create-temp-file) ; Creates temp file
(fs/create-temp-file {:prefix "data-" ; Custom prefix/suffix
:suffix ".json"})
(fs/create-temp-dir) ; Creates temp directory
(fs/create-temp-dir {:prefix "workdir-"})
;; Create links
(fs/create-link "link-name" "target") ; Hard link
(fs/create-sym-link "symlink" "target") ; Symbolic link
;; Temporary directory context
(fs/with-temp-dir [tmp-dir {:prefix "work-"}]
(println "Working in" (str tmp-dir))
;; Do work with tmp-dir
;; Directory automatically deleted after
)
```
## Reading and Writing Files
### Reading Files
```clojure
;; Read entire file
(slurp (fs/file "data.txt")) ; As string
;; Read lines
(with-open [rdr (io/reader (fs/file "data.txt"))]
(doall (line-seq rdr)))
;; Or use fs helpers
(fs/read-all-lines "data.txt") ; Returns seq of lines
(fs/read-all-bytes "binary-file") ; Returns byte array
```
### Writing Files
```clojure
;; Write text
(spit (fs/file "output.txt") "Hello, world!")
;; Write lines
(fs/write-lines "output.txt"
["Line 1" "Line 2" "Line 3"])
(fs/write-lines "output.txt"
["More lines"]
{:append true}) ; Append mode
;; Write bytes
(fs/write-bytes "output.bin" byte-array)
(fs/write-bytes "output.bin" byte-array
{:append true})
```
## Copying, Moving, and Deleting
```clojure
;; Copy files
(fs/copy "source.txt" "dest.txt") ; Copy file
(fs/copy "source.txt" "dest.txt"
{:replace-existing true}) ; Overwrite if exists
;; Copy entire directory trees
(fs/copy-tree "source-dir" "dest-dir") ; Recursive copy
(fs/copy-tree "source-dir" "dest-dir"
{:replace-existing true})
;; Move/rename
(fs/move "old-name.txt" "new-name.txt") ; Move or rename
(fs/move "file.txt" "other-dir/") ; Move to directory
;; Delete
(fs/delete "file.txt") ; Delete single file
(fs/delete-if-exists "maybe-file.txt") ; No error if missing
(fs/delete-tree "directory") ; Delete directory recursively
;; Delete on exit
(fs/delete-on-exit "temp-file.txt") ; Delete when JVM exits
```
## Listing and Traversing Directories
### Simple Listing
```clojure
;; List directory contents
(fs/list-dir ".") ; Seq of paths in directory
(fs/list-dir "." "*.txt") ; With glob pattern
;; List multiple directories
(fs/list-dirs ["dir1" "dir2"] "*.clj") ; Combine results
;; Get directory stream (more efficient for large dirs)
(with-open [ds (fs/directory-stream "." "*.txt")]
(doseq [path ds]
(println path)))
```
### Walking Directory Trees
```clojure
;; Walk directory tree
(fs/walk-file-tree "."
{:visit-file (fn [path attrs]
(println "File:" path)
:continue)
:pre-visit-dir (fn [path attrs]
(println "Entering:" path)
:continue)
:post-visit-dir (fn [path ex]
(println "Leaving:" path)
:continue)})
;; Common options
;; :max-depth - limit depth
;; :follow-links - follow symbolic links
;; :visit-file - called for each file
;; :pre-visit-dir - called before visiting directory
;Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.