# Using Clojure to Delete Directories Containing Symlinks

As part of repository maintenance, I often use a script to delete a group of directories, even if those directories are not empty. It looks something like this:

(require '[clojure.java.io :as io])
.
.
.
(defn delete-children-recursively! [f]
"Given a file, delete it. If the file is a directory delete its
contents first. This version does not handle symlinks."
(when (.isDirectory f)
(doseq [f2 (.listFiles f)]
(delete-children-recursively! f2)))
(when (.exists f) (io/delete-file f)))

(defn delete-clean-targets! [v]
"Given a vector of directory names (strings), delete the directories
and any files they contain."
(doseq [dir-name v]
(let [dir-file (io/file dir-name)]
(delete-children-recursively! dir-file))))

(delete-clean-targets! clean-targets)
(System/exit 0)


Somewhere, clean-targets is defined as a vector of directory names. When passed to the delete-clean-targets! function, all of those directories and their contents are removed.

But if any of the directories contain a symlink, it will not be deleted, and the directory where it resides will not be deleted either since it will not be empty.

The Files class provides a way to handle things such that the file can be deleted even if it is a symlink. The revised function looks something like this:

(import [java.nio.file Files LinkOption Path Paths])
.
.
.
(defn delete-children-recursively! [f]
"Given a file, delete it. If the file is a directory delete its
not the file it links to."
(when (.isDirectory f)
(doseq [f2 (.listFiles f)]
(delete-children-recursively! f2)))
(let [file-name (.getAbsolutePath f)
fp (Paths/get file-name (into-array String []))]
(try

There are a couple of interesting changes here, particularly the handling of optional arguments. For interoperability, those arguments get packed up into a native Java array as shown in the call to Files/exists with the inclusion of the NOFOLLOW_LINKS argument. It is also required when there are no additional argument, such as the call to Paths/get.
Note that using the NOFOLLOW_LINKS option means that only the symlink will be deleted, not the file that it points at.