使用Clojure创建符号链接

5

最近,我一直在关注Clojure作为一种可能用于系统脚本编写的函数式语言。但是,我意识到使用JVM作为底层意味着我受限于Java的能力。

那么,如何创建符号链接?或硬链接?我的意思是不使用(sh "ln" ...)命令。

5个回答

2
您可以使用Java Native Access来访问目标主机上的本地库。
简单示例:
(ns jna-test
    (:import 
     (com.sun.jna Native Function)))

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

还有可用的Clojure封装器: clj-nativeclojure-jna

2

啊,这确实很烦人。我不确定sh选项到底有多糟糕... 话虽如此,Ant提供了一个符号链接任务,你可以通过Lancet以合理的Clojure友好方式使用它,Lancet是Stuart Halloway在他的《Programming Clojure》书中最初介绍的Ant包装器,目前由Leiningen内部使用。如果你想在Leiningen中看到符号链接任务的效果,请查看1.3.0版本中的这一行


1
还可以看看未来可能会更好的 - Michał Marczyk
我想每种编程语言都有它自己的问题。 - qrest
哦烦恼,现在我不确定lein中的符号链接是否有效...我想一个人应该把这看作是测试内心平静的机会。 - Michał Marczyk
哦!我看到,在Path类中,我们可能会得到一个isHidden方法。这是否意味着能够创建隐藏文件...?终于有了吗?未来是光明的。(抱歉偏离主题...)我认为sh选项可能是您最好的选择;符号链接不是真正的跨平台,因此在Java中缺乏支持。 - Isaac
这里有一篇很好的文章,介绍了如何通过JNI在Java中区分符号链接和常规文件。顺便说一句,我从来没有理解过“符号链接不可移植”的想法。至少一个.isSymbolicLink方法将是完全跨平台的(如果托管文件的平台首先不支持符号链接,则返回false,如果由于某种原因它无法发现正确答案,则可能会抛出异常),对吧?(Java有时令人沮丧。) - Michał Marczyk
完全同意。这很恼人,这也是不支持创建隐藏文件的相同理由。愚蠢。 - Isaac

0
你可以利用这个库https://github.com/ToBeReplaced/nio.file,我用过了。
(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")

需要相关的权限才能操作。例如,在Windows 7的Emacs/Cider环境中运行时,需要从管理员命令窗口启动emacs,否则会出现“FileSystemException java.nio.file.FileSystemException: c:\tmp\myFolder\test.txt: A required privilege is not held by the client”的错误提示。


0

这是一个旁注:

当使用Clojure进行系统命令时,如果您使用cake而不是leiningen,它可以使用持久的JVM,因此每次运行命令时无需等待三秒钟启动JVM。

*cake不太稳定,因此有些日子它比其他日子表现更好。(截至2010年9月)


0
(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))))

这就是我想出来的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接