Shell scripting with Clojure

We had a nice afterwork Clojure learning session with a colleague the other day during which we quickly hacked together a shell script that reads a directory containing Selenium test result files and outputs all the failed test cases. (Why we haven’t automated the Selenium test running and result reporting with e.g. Jenkins is another story..)

In the session I learned at least about the following:

  • making standalone command-line executable Clojure scripts (as long as you have Leiningen installed) that still use Leiningen to handle the dependencies
  • reading and writing files
  • using Enlive to parse and look up particular data from HTML files

In this post, I’ll describe how to create command-line executable Clojure scripts with lein-exec. In a later post I will describe the test result parsing script we put together.

Command-line executable Clojure scripts with lein-exec

The only prerequisite here is that you have Leiningen installed but it should be pretty safe to assume this as lein seems to be the de facto build tool for Clojure.

Now, when you want to do quick standalone Clojure scripts without having to create a complete lein project, but still want to use lein to manage the dependencies to any 3rd party libraries, there is a nice lein plugin called lein-exec.

The installation is simple (the following assumes Leiningen 2, see the lein-exec readme for 1.x installation instructions). A global installation (meaning you can use lein-exec any time you call lein, rather than specifying it as a project-specific plugin) of lein-exec is done by adding the following to your ~/.lein/profiles.clj (if profiles.clj doesn’t exist, create it first).

;; as of writing this, 0.3.1 was the latest version
{:user {:plugins [[lein-exec "0.3.1"]]}}  

Now we can quickly create and run scripts:

(println (+ 1 2))

running foo.clj:

$ lein exec foo.clj

This isn’t that impressive yet, but once you add dependencies to third-party libraries, the usefulness becomes more apparent:

(require 'leiningen.exec)

;; Add a dependency to the classpath on the fly
(leiningen.exec/deps '[[enlive/enlive "1.1.4"]])

(require '[net.cgrand.enlive-html :as html])

;; Grab and print the title element from the Google front page using Enlive
(println (html/select (html/html-resource ( "")) [:title]))

and let’s run it:

$ lein exec bar.clj
({:tag :title, :attrs nil, :content (Google)})

Now lein and lein-exec handle the enlive dependency behind the scenes. This is nice as now you have all the power of the Clojure ecosystem available for you even in quick one-off scripts.

It is also possible to make the scripts executable themselves if you are in a *nix environment. You need to download a lein-exec script and save it somewhere in your path. Also, if your lein executable is called something else than `lein`, you have to modify the lein-exec script to reflect that.

$ wget # download
$ chmod a+x lein-exec # make the script executable
$ mv lein-exec ~/bin # move to ~/bin, assuming it is in PATH

Now if you add the following to the first line of your script:

#!/usr/bin/env lein-exec
(println (+ 1 2))

you can execute the script directly (as long as you give it the execute permission):

$ chmod +x foo.clj
$ ./foo.clj
$ 3

That’s it for now. I will follow up with the Selenium test result parsing script soon.

Read more about stand-alone Clojure scripting: