问题 如何使用Clojure在命令行中更改目录?


我正在寻找的是Windows命令行中的这种命令行交互:

C:\temp1>clj some_script.clj
C:\temp2>

some_script.clj包含以下内容:

(cd "c:\\temp2")

所以问题是 - 我如何实现功能cd?已经尝试过clojure.java.shell,但它看起来不像我需要的lib。这可能是一个简单的问题,问题可能是我不能流利使用Java?!


5420
2017-10-13 08:00


起源

clj some_script.clj 在另一个进程中执行,因此它无法更改终端会话的当前目录。无论语言如何,你都无法做你想做的事。 - bfontaine
但是,您可以使用shell脚本执行此操作。而且我确信必须有一种方法来破解父进程并以某种方式从另一个进程更改当前目录,但我想这不容易/实用。 - Torbjørn
如果你在当前会话中加载* shell脚本,你可以这样做;只是执行脚本将无法正常工作。 - bfontaine
如果我们还在谈论Windows命令行(批处理脚本),那么它确实有效。在香草bash它没有。 - Torbjørn
对;我读得太快,并没有看到它是一个特定于Windows的问题。 - bfontaine


答案:


你不能用Java做到这一点,所以你不能在Clojure中做到这一点。看到 在Java中更改当前工作目录?


13
2017-10-13 08:15



这真的很难相信。总有办法,不是吗?嗯,也许我最终会得到一个多语言解决方案,从clojure到ruby进行目录更改...... :) - Torbjørn
也很难相信类路径在运行时是固定的,但它确实如此。 Hotspot是一个奇妙的工程实力和愚蠢错误的奇怪组合。
工作目录是一个非常特定于平台的功能。实际上,我认为对于与Java等平台无关的语言来说,这是一个非常好的设计决策,以避免与特定于平台的语义相关联,尤其是当有很多其他方法可以实现相同的结果时。我敢肯定,如果你真的有决心,你可以使用JNI以特定于平台的方式解决问题。 - mikera


clojure可以做到这一点。 您只需要更改一个名为的动态全局变量 *sh-dir*。在repl中运行以下代码:

 (use '[clojure.java.sh])
 (sh "ls")
    => {:exit 0, :out "LICENSE\nREADME.md\nauto_deploy.iml\ndoc\nproject.clj\nresources\nsrc\ntarget\ntest\n", :err ""}

    (binding [*sh-dir* "c:/"] (sh "ls"))
{:exit 0,
 :out "$360Section
       $GetCurrent
       $Recycle.Bin
       Boot
       Documents and Settings
       ImbaMallLog.txt
       Intel
       MSOCache
       OEMSY
       PerfLogs
       Program Files
       Program Files (x86)
       ProgramData
       Python27
       Recovery
       System Volume Information
       Users
       Windows
       apache-ant-1.9.3
       bootmgr
       hiberfil.sys
       inetpub
       pagefile.sys
       ",
 :err ""}

有关详细信息,请参阅doc。您可以使用 (alter-var-root #'clojure.java.shell/*sh-dir* (constantly "the-cd-path")) 不断改变它。感谢isaac告诉我这件事。 希望这可以帮助。


2
2017-07-22 02:52



虽然有趣但我不确定你是否真的解决了问题中陈述的问题。至少你没有证明它。 - Torbjørn
我不能说得更清楚。 - Song Zhang
您没有证明当前目录在程序运行的终端会话中发生了更改 - 程序退出后更改仍然存在 - 这就是我的要求。 - Torbjørn