web-dev-qa-db-ja.com

Groovyで現在の作業ディレクトリを変更する方法

今、私は他の人のインターフェースを呼び出すためのGroovyスクリプトを書いています。ただし、スクリプトを実行するときに、現在の作業パスを変更する必要があります。私はそれがJavaでは不可能であることを知っています。 Groovyで可能ですか?

11
Joe

GroovyはJVMで実行されるため、同じ制限が適用されます。残念ながらそれは不可能です。

Javaで現在の作業ディレクトリを変更しますか?

JDKバグ

7
Grzegorz Żur

他のスクリプトを別のプロセスとして実行できる場合は、ProcessBuilderパラメーターの作業ディレクトリを指定できます。

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

または

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

そのため、プロセスは新しいフォルダに切り替わり、そこで実行されます。

19
kirill-a

Java/groovyは、私が知る限り、実際には作業ディレクトリを「持っている」わけではありません。 groovyを起動したシェルには、そのシェルから直接継承される子の「コマンド」が1つあります。

Javaはまた、シェルの現在のディレクトリを読み取り、それを「user.dir」に格納しているようです。これは「File」オブジェクトのベースとして使用されるため、System.setProperty( "user.dir"、 "c:/ windows")を実行すると、新しいFile( "。")の今後の呼び出しは変更されますが、親シェルディレクトリ(したがって、子ディレクトリではありません)。

さまざまなシナリオで機能する可能性のある3つの「回避策」を次に示します。

1)私は非常に特定のタスクでこれを克服しました...「cd」をGroovyスクリプトとして実装したかったのです。すべてのスクリプトがすでにバッチファイルに「ラップ」されていたためにのみ可能でした。スクリプトが「afterburner.cmd」というファイルを作成できるようにしました。このファイルが存在する場合は、スクリプトの終了時に実行されます。これを機能させるために、いくつかのバッチファイルのトリックがありました。

起動コマンドファイルは、Groovyスクリプト/アプリを呼び出す前に現在のディレクトリを「設定」することもできます。

ちなみに、スタートアップcmdを使用すると、思っていたよりもはるかに便利になりました。環境が一定になり、「スクリプト」を他のマシンに簡単に展開できるようになります。スクリプトを.classesにコンパイルすることもできます。これは、スクリプトを「groovy」で実行するよりも、.groovyを.classにコンパイルし、.classを「Java」で開始する方が速いことがわかったためです。通常、コンパイル手順をスキップして、大幅に高速化できます。

2)いくつかの小さなコマンドの場合、次のようなメソッドを作成できます。

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")  

「cmd」が不要な場合は、「。execute()」よりも遅くなります。

3)「Open」コマンドシェルを維持する小さなクラスをコーディングします(これは一度実行しましたが、少し複雑です)が、アイデアは次のとおりです。

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

これで、「in」はスピンオフ/読み取り可能な入力ストリームであり、「out」はコマンドを書き込むことができる出力ストリームであり、「err」に注意してエラーを検出します。

クラスは、出力にコマンドを書き込み、コマンドが完了するまで入力を読み取り、出力をユーザーに返す必要があります。

問題は、特定のコマンドの出力がいつ完了したかを検出することです。一般に、「C:...」プロンプトを検出して、これはコマンドの実行が終了したことを意味すると想定できます。タイムアウトを使用することもできます。どちらもかなり間違いやすいです。そのシェルのプロンプトをユニークなものに設定して、フォールしにくくすることができます。

利点は、このシェルをアプリの存続期間中ずっと開いたままにしておくことができ、「cmd」シェルを繰り返し作成しないため、速度を大幅に向上できることです。 Processオブジェクトをラップするクラス(「CommandShell」と呼びましょう)を作成する場合は、非常に使いやすいはずです。

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

私は一度このようなGroovyクラスを作成しました。これは多くの実験であり、インスタンスは「exit」などのコマンドによって破棄される可能性がありますが、それは可能です。

2
Bill K