开发者

Use Clojure to create symlink

开发者 https://www.devze.com 2023-01-12 03:46 出处:网络
I\'ve been focusing on Clojure recently as a possible functional language to do systems scripting. Until, it dawned 开发者_运维百科on me that having the JVM underneath means I\'m limited to Java\'s ca

I've been focusing on Clojure recently as a possible functional language to do systems scripting. Until, it dawned 开发者_运维百科on me that having the JVM underneath means I'm limited to Java's capability.

So, how do I create a symlink? Or a hard link? I mean without (sh "ln" ...).


Ah, this is indeed a pain. I'm not sure the sh option is all that bad, actually... Having said that, Ant provides a symlink task which you could use in a reasonably Clojure-friendly way through Lancet, the Ant wrapper originally introduced by Stuart Halloway in his "Programming Clojure" book and currently used internally by Leiningen. If you want to see the symlink task in action in Leiningen, have a look at this line in the 1.3.0 release.


You could use Java Native Access to access native libs on the target host.

Simple example:

(ns jna-test
    (:import 
     (com.sun.jna Native Function)))

 (defn symlink [oldpath newpath]
    (-> (Function/getFunction "c" "symlink")
    (.invoke Integer (to-array [oldpath newpath]))))

There are also Clojure wrappers awailable: clj-native and clojure-jna


It's something of a side note:

when using Clojure for system commands, if you use cake instead of leiningen it can use a persistent JVM so you dont have to wait three seconds for the JVM to start every time you run a command.

*cake is not very stable so some days it works much better than others. (as of Sep. 2010)


You can take advantage of this library https://github.com/ToBeReplaced/nio.file which works for me

(require '[org.tobereplaced.nio.file :refer [create-symbolic-link! ] :as nio])

(defn createSimLink [ targetPath newLink ]
  (let [theName (.getName (File. targetPath))]
    (try
      (nio/create-symbolic-link!  (str  newLink "/" theName)  targetPath  )
      (catch Exception e (prn "error " e)))))

(createSimLink "c:/tmp/test.txt" "c:/tmp/myFolder")

Note related privilege is needed. E.g. to run it in Windows 7 in Emacs/Cider environment, the emacs needs to be started from an admin command window, otherwise it will complain "FileSystemException java.nio.file.FileSystemException: c:\tmp\myFolder\test.txt: A required privilege is not held by the client"


(require '[clojure.java.io :as io])
(import '[java.nio.file Files Paths]
        '[java.nio.file.attribute FileAttribute])

(def user-home (System/getProperty "user.home"))
(def user-pwd (System/getProperty "user.dir"))

(defn path [p]
  (let [expanded (.replaceFirst p "^~" user-home)]
    (Paths/get expanded (make-array String 0))))

(defn symlink
  [link target & attrs]
  (let [link-path (path link)
        target-path (path (.getPath (io/file user-pwd target)))]
    (Files/createSymbolicLink link-path target-path (into-array FileAttribute attrs))))

That's what I came up with.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号