I have a folder structure like this:
I've created my runnable jar with lein uberjar
.
When running my jar, I want to list the subfolders of a
.
I know I can get the contents of resources/a/b/x.txt using clojure.java.io
(slurp (clojure.java.io/resource "a/b/x.txt"))
But I can't find a simple way to list the subfolders.
(clojure.java.io/file (clojure.java.io/resource "a"))
just results in a java.lang.IllegalArgumentException: Not a file
because it isn't a file, it's a resource inside the jar file.
Is there a library that does this?
here is the port of code from the java specific answer:
(ns my-project.core
(:require [clojure.string :as cs])
(:import java.util.zip.ZipInputStream)
(:gen-class))
(defrecord HELPER [])
(defn get-code-location []
(when-let [src (.getCodeSource (.getProtectionDomain HELPER))]
(.getLocation src)))
(defn list-zip-contents [zip-location]
(with-open [zip-stream (ZipInputStream. (.openStream zip-location))]
(loop [dirs []]
(if-let [entry (.getNextEntry zip-stream)]
(recur (conj dirs (.getName entry)))
dirs))))
(defn -main [& args]
(println (some->> (get-code-location)
list-zip-contents
(filter #(cs/starts-with? % "a/")))))
Being put to a main namespace and run with jar will output all the paths in the /resources/a
folder..
java -jar ./target/my-project-0.1.0-SNAPSHOT-standalone.jar
;;=> (a/ a/b/ a/b/222.txt a/222.txt)
Also some quick research lead me to this library: https://github.com/ronmamo/reflections
it shortens the code, but also requires some dependencies for the project (i guess it could be undesirable):
[org.reflections/reflections "0.9.11"]
[javax.servlet/servlet-api "2.5"]
[com.google.guava/guava "23.0"]
and the code is something like this:
(ns my-project.core
(:require [clojure.string :as cs])
(:import java.util.zip.ZipInputStream
[org.reflections
Reflections
scanners.ResourcesScanner
scanners.Scanner
util.ClasspathHelper
util.ConfigurationBuilder])
(:gen-class))
(defn -main [& args]
(let [conf (doto (ConfigurationBuilder.)
(.setScanners (into-array Scanner [(ResourcesScanner.)]))
(.setUrls (ClasspathHelper/forClassLoader (make-array ClassLoader 0))))]
(println
(filter #(cs/starts-with? % "a/")
(.getResources (Reflections. conf) #".*")))))