10

In ruby I frequently use File.expand_path(File.dirname(__FILE__)) for loading config files or files with test data. Right now I'm trying to load some html files for a test in my clojure app and I can't figure out how to do it without hard coding the full path to the file.

edit: I'm using leinigen if that helps in any way

ref: __FILE__ is a special literal which returns the filename (including any path) given to the program when executed. see (rubydoc & perldata)

draegtun
  • 22,441
  • 5
  • 48
  • 71
jshen
  • 11,507
  • 7
  • 37
  • 59

4 Answers4

13
*file*

API Reference (add *file* to the url)

9

Here is one way to replicate that in Clojure:

(defn dirname [path]
  (.getParent (java.io.File. path)))

(defn expand-path [path]
  (.getCanonicalPath (java.io.File. path)))

Then your Ruby line File.expand_path(File.dirname(__FILE__)) in Clojure would be this:

(expand-path (dirname *file*))

See Java interop docs for .getParent & .getCanonicalPath.


NB. I think *file* always returns the absolute (though not canonical) pathname/filename in Clojure. Whereas __FILE__ returns the the pathname/filename provided at execution. However I don't think these difference should effect what your trying to do?

/I3az/

draegtun
  • 22,441
  • 5
  • 48
  • 71
8

Neither of the 9 point solutions is correct. *file* gives you a file relative to the classpath. Using .getCanonicalPath or .getAbsolutePath on *file* will give you a nonexistant file. As pointed out in this old thread, you need to use ClassLoader to resolve *file* correctly. Here's what I use to get the parent directory of the current file:

(-> (ClassLoader/getSystemResource *file*) clojure.java.io/file .getParent)
cldwalker
  • 6,155
  • 2
  • 27
  • 19
1

Based on user83510's answer above, the full answer is:

(def path-to-this-file 
  (clojure.string/join "/" [(-> (ClassLoader/getSystemResource *file*) clojure.java.io/file .getParent) (last (clojure.string/split *file* #"/"))]))

It ain't pretty but it works :P

boxed
  • 3,895
  • 2
  • 24
  • 26