Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27276

Clojure create directory hierarchy - but not in a procedural way

Let's say I need to create the following directory structure in Clojure:

a
\--b
|   \--b1
|   \--b2
\--c
   \-c1

Instead of doing procedural things like the following:

(def a (File. "a"))
(.mkdir a)
(def b (File. a "b"))
(.mkdir b)
;; ...

... is there a clever way to somehow represent the above actions as data, declaratively, and then create the hierarchy in one fell swoop?

Upvotes: 10

Views: 3694

Answers (2)

foomip
foomip

Reputation: 574

Another option if you want to easily handle creating recursive directories is to use .mkdirs

user> (require '[clojure.java.io :as io]')
user> (.mkdirs (io/file "a/b/c/d"))

You can use absolute path eg. /a/b/c/d or else it will be created relative to the path you initiated the repl from.

Also handy to check if given path is not an existing directory

user> (.isDirectory (io/file "a/b/c/d"))

Upvotes: 2

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91534

a quick and simple approach would be to make a vector of dirs to create and map mkdir on to it:

user> (map #(.mkdir (java.io.File. %)) ["a", "a/b" "a/b/c"])
(true true true)

or you can specify your dir structure as a tree and use zippers to walk it making the dirs on the way:

(def dirs ["a" ["b" ["b1" "b2"]] ["c" ["c1"]]])
(defn make-dir-tree [original]
  (loop [loc (zip/vector-zip original)]
    (if (zip/end? loc)
      (zip/root loc)
      (recur (zip/next
              (do (if (not (vector? (zip/node loc)))
                    (let [path (apply str (interpose "/" (butlast (map first (zip/path loc)))))
                          name (zip/node loc)]
                      (if (empty? path)
                        (.mkdir (java.io.File. name))
                        (.mkdir (java.io.File. (str path "/" name))))))
                  loc))))))
(make-dir-tree dirs)

.

arthur@a:~/hello$ find a
a
a/c
a/c/c1
a/b
a/b/c
a/b/b2
a/b/b1

If you are doing a lot of general systems administration then something heavier may be in order. The pallet project is a library for doing system administration of all sorts on physical and cloud hosted systems (though it tends to lean towards the cloudy stuff). Specifically the directory

Upvotes: 10

Related Questions