6.8 KiB
6.8 KiB
Babashka.fs Quick Reference
Setup
(require '[babashka.fs :as fs])
File Checks
(fs/exists? path) ; Does it exist?
(fs/directory? path) ; Is it a directory?
(fs/regular-file? path) ; Is it a regular file?
(fs/sym-link? path) ; Is it a symbolic link?
(fs/hidden? path) ; Is it hidden?
(fs/readable? path) ; Can read?
(fs/writable? path) ; Can write?
(fs/executable? path) ; Can execute?
Creating
(fs/create-file path) ; Empty file
(fs/create-dir path) ; Single directory
(fs/create-dirs path) ; With parents
(fs/create-temp-file) ; Temp file
(fs/create-temp-file {:prefix "x-" :suffix ".txt"})
(fs/create-temp-dir) ; Temp directory
(fs/create-sym-link "link" "target") ; Symbolic link
Reading/Writing
(slurp path) ; Read as string
(spit path content) ; Write string
(fs/read-all-lines path) ; Read lines
(fs/write-lines path ["line1" "line2"]) ; Write lines
(fs/read-all-bytes path) ; Read bytes
(fs/write-bytes path byte-array) ; Write bytes
Copying/Moving/Deleting
(fs/copy src dest) ; Copy file
(fs/copy src dest {:replace-existing true}) ; Overwrite
(fs/copy-tree src dest) ; Copy directory
(fs/move src dest) ; Move/rename
(fs/delete path) ; Delete
(fs/delete-if-exists path) ; Delete (no error)
(fs/delete-tree path) ; Recursive delete
(fs/delete-on-exit path) ; Delete when JVM exits
Listing
(fs/list-dir ".") ; List directory
(fs/list-dir "." "*.txt") ; With glob
(fs/list-dirs ["dir1" "dir2"] "*.clj") ; Multiple dirs
Searching
(fs/glob "." "**/*.clj") ; Recursive search
(fs/glob "." "*.{clj,edn}") ; Multiple extensions
(fs/match "." "regex:.*\\.clj" {:recursive true})
Common Glob Patterns
"*.txt" ; Files ending in .txt
"**/*.clj" ; All .clj files recursively
"**{.clj,.cljc}" ; Multiple extensions recursive
"src/**/*_test.clj" ; Test files under src/
"data/*.{json,edn}" ; JSON or EDN in data/
Path Operations
(fs/path "dir" "file.txt") ; Join paths
(fs/file-name path) ; Get filename
(fs/parent path) ; Get parent directory
(fs/extension path) ; Get extension ("txt")
(fs/split-ext path) ; ["name" "ext"]
(fs/strip-ext path) ; Remove extension
(fs/components path) ; All path parts
(fs/absolutize path) ; Make absolute
(fs/relativize base target) ; Relative path
(fs/normalize path) ; Normalize (remove ..)
(fs/canonicalize path) ; Canonical path
Metadata
(fs/size path) ; Size in bytes
(fs/creation-time path) ; FileTime
(fs/last-modified-time path) ; FileTime
(fs/file-time->millis file-time) ; Convert to ms
(fs/owner path) ; Owner (Unix)
(str (fs/owner path)) ; Owner name
System Paths
(fs/home) ; User home
(fs/temp-dir) ; System temp
(fs/cwd) ; Current directory
(fs/exec-paths) ; PATH directories
(fs/which "git") ; Find executable
XDG Directories (Linux/Unix)
(fs/xdg-config-home) ; ~/.config
(fs/xdg-config-home "myapp") ; ~/.config/myapp
(fs/xdg-data-home) ; ~/.local/share
(fs/xdg-cache-home) ; ~/.cache
(fs/xdg-state-home) ; ~/.local/state
Archives
(fs/zip "archive.zip" ["file1" "file2"]) ; Create zip
(fs/unzip "archive.zip" "dest-dir") ; Extract all
Walking Trees
(fs/walk-file-tree root
{:visit-file (fn [path attrs]
(println path)
:continue)
:max-depth 3
:follow-links false})
Temporary Files
;; Auto-cleanup with temp directory
(fs/with-temp-dir [tmp {}]
(let [f (fs/path tmp "work.txt")]
(spit f "data")
(process f)))
;; tmp deleted here
;; Manual temp file
(let [tmp (fs/create-temp-file)]
(try
(spit tmp data)
(process tmp)
(finally (fs/delete tmp))))
Common Patterns
Find files modified in last N days
(defn recent? [days path]
(let [cutoff (- (System/currentTimeMillis)
(* days 24 60 60 1000))]
(> (fs/file-time->millis (fs/last-modified-time path))
cutoff)))
(->> (fs/glob "." "**/*.clj")
(filter (partial recent? 7)))
Process all files in directory
(doseq [f (fs/glob "data" "*.json")]
(when (fs/regular-file? f)
(process-file f)))
Safe file write (atomic)
(let [target "important.edn"
tmp (fs/create-temp-file {:dir (fs/parent target)})]
(try
(spit tmp data)
(fs/move tmp target {:replace-existing true})
(catch Exception e
(fs/delete-if-exists tmp)
(throw e))))
Backup file with timestamp
(defn backup [path]
(let [backup-name (str path ".backup."
(System/currentTimeMillis))]
(fs/copy path backup-name)))
Clean old logs
(defn clean-old-logs [dir days]
(->> (fs/glob dir "*.log")
(remove (partial recent? days))
(run! fs/delete)))
Tips
✅ DO:
- Use
fs/pathto join paths (cross-platform) - Use
with-temp-dirfor auto-cleanup - Check
fs/exists?before operations - Use glob for finding files
- Filter early in pipelines
❌ DON'T:
- Manually concatenate paths with
/ - Forget to handle missing files
- Use
list-dirfor large directories (usedirectory-stream) - Forget to close streams (use
with-open)
Error Handling
;; Check first
(when (fs/exists? "config.edn")
(process-config))
;; Try-catch for specific errors
(try
(process-file path)
(catch java.nio.file.NoSuchFileException e
(println "File not found"))
(catch java.nio.file.AccessDeniedException e
(println "Access denied")))