Claude
Skills
Sign in
Back

babashka.fs

Included with Lifetime
$97 forever

A guide to using babashka.fs.

General

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