12

What I'm looking for is this kind of command line interaction at the Windows command line:

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

Where some_script.clj contains something like:

(cd "c:\\temp2")

So the question is - how do I implement the function cd? Have experimented with clojure.java.shell, but it does not look like the lib I need. This might be a simple question, the problem might be that I'm not fluent in Java?!

Torbjørn
  • 6,423
  • 5
  • 29
  • 42
  • `clj some_script.clj` is executed in another process so it can’t change the terminal session’s current directory. You can’t do what you want, whatever the language. – bfontaine Aug 08 '17 at 08:37
  • You could however do it with a shell script. And I'm sure there has to be a way to hack into the parent process and change the current directory from another process somehow, but I guess it's not easy/practical. – Torbjørn Aug 09 '17 at 12:36
  • You could do it if you* load* the shell script in the current session; merely executing the script won’t work. – bfontaine Aug 09 '17 at 12:38
  • If we're still talking about windows command line (batch script) then it does work. In vanilla bash it does not. – Torbjørn Aug 09 '17 at 13:08
  • Right; I read too fast and didn’t see it was a Windows-specific question. – bfontaine Aug 09 '17 at 13:15

2 Answers2

14

You can't do this in Java, so you can't do it in Clojure. See Changing the current working directory in Java?

Community
  • 1
  • 1
Stefan Tilkov
  • 1,683
  • 12
  • 10
  • 3
    That is really hard to believe. There's always a way, isn't there? Hmm, maybe I'll end up with a polyglot solution, shelling out from clojure to ruby for the directory change... :) – Torbjørn Oct 13 '10 at 08:23
  • 2
    It's also hard to believe the classpath is fixed at runtime, but it's true. Hotspot is a bizarre mix of amazing engineering prowess and boneheaded mistakes. –  Oct 13 '10 at 17:02
  • Working directories are a very platform-specific feature. I actually think it's a very good design decision for a platform-independent language such as Java to avoid being tied to platform specific semantics, especially when there are plenty of other ways to achieve the same result. I'm sure if you are really determined, you could solve the problem in a platform-specific way using JNI. – mikera Oct 14 '10 at 00:00
3

clojure can do this. You only need to change a dynamic global variable called *sh-dir*. run the following code in your 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 ""}

see the doc for more info. you can use (alter-var-root #'clojure.java.shell/*sh-dir* (constantly "the-cd-path")) to change it constantly. Thanks for isaac telling me about this. Hope this helps.

Song Zhang
  • 315
  • 1
  • 5
  • While interesting I'm not sure you actually solve the problem stated in the question. At least you don't demonstrate it. – Torbjørn Aug 08 '16 at 08:48
  • 1
    You did not demonstrate that the current directory changed in the terminal session where your program ran - that the change persisted after the program exited - which was what I asked. – Torbjørn Sep 27 '16 at 13:59