230 lines
6.8 KiB
Markdown
230 lines
6.8 KiB
Markdown
# Babashka.fs Quick Reference
|
|
|
|
## Setup
|
|
```clojure
|
|
(require '[babashka.fs :as fs])
|
|
```
|
|
|
|
## File Checks
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(fs/list-dir ".") ; List directory
|
|
(fs/list-dir "." "*.txt") ; With glob
|
|
(fs/list-dirs ["dir1" "dir2"] "*.clj") ; Multiple dirs
|
|
```
|
|
|
|
## Searching
|
|
```clojure
|
|
(fs/glob "." "**/*.clj") ; Recursive search
|
|
(fs/glob "." "*.{clj,edn}") ; Multiple extensions
|
|
(fs/match "." "regex:.*\\.clj" {:recursive true})
|
|
```
|
|
|
|
### Common Glob Patterns
|
|
```clojure
|
|
"*.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
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(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)
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(fs/zip "archive.zip" ["file1" "file2"]) ; Create zip
|
|
(fs/unzip "archive.zip" "dest-dir") ; Extract all
|
|
```
|
|
|
|
## Walking Trees
|
|
```clojure
|
|
(fs/walk-file-tree root
|
|
{:visit-file (fn [path attrs]
|
|
(println path)
|
|
:continue)
|
|
:max-depth 3
|
|
:follow-links false})
|
|
```
|
|
|
|
## Temporary Files
|
|
```clojure
|
|
;; 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
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(doseq [f (fs/glob "data" "*.json")]
|
|
(when (fs/regular-file? f)
|
|
(process-file f)))
|
|
```
|
|
|
|
### Safe file write (atomic)
|
|
```clojure
|
|
(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
|
|
```clojure
|
|
(defn backup [path]
|
|
(let [backup-name (str path ".backup."
|
|
(System/currentTimeMillis))]
|
|
(fs/copy path backup-name)))
|
|
```
|
|
|
|
### Clean old logs
|
|
```clojure
|
|
(defn clean-old-logs [dir days]
|
|
(->> (fs/glob dir "*.log")
|
|
(remove (partial recent? days))
|
|
(run! fs/delete)))
|
|
```
|
|
|
|
## Tips
|
|
|
|
✅ **DO:**
|
|
- Use `fs/path` to join paths (cross-platform)
|
|
- Use `with-temp-dir` for 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-dir` for large directories (use `directory-stream`)
|
|
- Forget to close streams (use `with-open`)
|
|
|
|
## Error Handling
|
|
```clojure
|
|
;; 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")))
|
|
```
|