Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the current working directory in Groovy

Tags:

groovy

cwd

Now, I am writting a Groovy script to invoke other's interface. But I need change my current working path when running the script. I know it is not possible in Java. Is it possible in Groovy?

like image 970
Joe Avatar asked Aug 12 '13 03:08

Joe


4 Answers

If you can run other script as separate process, you can give ProcessBuilder parameter working dir:

def processBuilder=new ProcessBuilder(command)
processBuilder.directory(new File("Working dir"))
def process = processBuilder.start()

or

command.execute(null, new File("Working dir"))

so that process will switch to your new folder and execute it there.

like image 54
kirill-a Avatar answered Oct 10 '22 15:10

kirill-a


As Groovy runs on JVM, the same restrictions apply. Unfortunately it is not possible.

Changing the current working directory in Java?

JDK bug

like image 43
Grzegorz Żur Avatar answered Oct 10 '22 15:10

Grzegorz Żur


Java/groovy doesn't really "Have" a working directory as far as I can tell. The shell that launched groovy has one and any child "commands" inherit from that shell diretly.

Java also seems to read the current directory of the shell and store it in "user.dir". This is used as a base for the "File" object so if you System.setProperty("user.dir", "c:/windows") it will change future invocations of new File(".") but will not change the parent shell directory (and therefore not the child directories).

Here are three "Work-Arounds" that may work for different scenarios:

1) I KIND OF overcame this for a very specific task... I wanted to implement "cd" as a groovy script. It was only possible because all my scripts were already being "wrapped" in a batch file. I made it so that my script could create a file called "afterburner.cmd" that, if it existed, would be executed when the script exits. There was some batch file trickery to make this work.

A startup cmd file could also "Set" the current directory before invoking your groovy script/app.

By the way, Having a startup cmd has been much more helpful than I'd thought it would be--It makes your environment constant and allows you to more easily deploy your "Scripts" to other machines. I even have mine compile my scripts to .classes because it turned out to be faster to compile a .groovy to a .class and start the .class with "Java" than it was to just run the script with "groovy"--and usually you can skip the compile step which makes it a LOT faster!

2) For a few small commands, you might write a method like this:

def currentDir = "C:\\"
def exec(command, dir = null) {
    "cmd /c cd /d ${dir?:currentDir} && $command".execute().text
}

// Default dir is currentDir
assert exec("dir").endsWith("C:\\>")

// different dir for this command only
assert exec("dir", "c:\\users").endsWith("C:\\users") 

// Change default dir
currentDir = "C:\\windows"
assert exec("dir").endsWith("C:\\windows")  

it will be slower than "".execute() if "cmd" is not required.

3) Code a small class that maintains an "Open" command shell (I did this once, there is a bit of complexity), but the idea is:

def process="cmd".execute()
def in=process.in
def out=process.out
def err=process.err

Now "in" is an input stream that you could spin off/read from and "out" is an output stream that you can write commands to, keep an eye on "err" to detect errors.

The class should write a command to the output, read the input until the command has completed then return the output to the user.

The problem is detecting when the output of any given command is complete. In general you can detect a "C:..." prompt and assume that this means that the command has finished executing. You could also use a timeout. Both are pretty fallible. You can set that shell's prompt to something unique to make it much less fallible.

The advantage is that this shell can remain open for the entire life of your app and can significantly increase speed since you aren't repeatedly creating "cmd" shells. If you create a class (let's call it "CommandShell") that wraps your Process object then it should be really easy to use:

def cmd=new CommandShell()
println cmd.execute("cd /d c:\\")
println cmd.execute("dir") // Will be the dir of c:\

I wrote a groovy class like this once, it's a lot of experimenting and your instance can be trashed by commands like "exit" but it's possible.

like image 40
Bill K Avatar answered Oct 10 '22 15:10

Bill K


you can wrap it up in a dir block. eg :

dir('yourdirectory') {
   codeblock
}
like image 22
developerinlondon Avatar answered Oct 10 '22 16:10

developerinlondon