如何在groovy中获取正在运行的脚本的路径?


68

我正在编写一个普通脚本,希望通过存储在同一文件夹中的属性文件进行控制。但是,我希望能够从任何地方调用此脚本。当我运行脚本时,它总是根据运行位置而不是脚本的位置查找属性文件。

如何从脚本内部访问脚本文件的路径?

Answers:


16

从Groovy 2.3.0开始,@groovy.transform.SourceURI注释可用于使用脚本位置的URI填充变量。然后可以使用此URI来获取脚本的路径:

import groovy.transform.SourceURI
import java.nio.file.Path
import java.nio.file.Paths

@SourceURI
URI sourceUri

Path scriptLocation = Paths.get(sourceUri)

请注意,这仅适用于URI为file:URI(或具有已安装FileSystemProvider的其他URI方案类型)的情况,否则调用将抛出FileSystemNotFoundExceptionPaths.get(URI)。某些groovy运行时(例如groovyshell和nextflow)将返回一个data:URI,该URI通常与installed不匹配FileSystemProvider


1
java.nio.file.FileSystemNotFoundException: Provider "data" not installed
Hugues Fontenelle

1
@HuguesFontenellesourceUri收到该异常有什么价值?还是在@SourceUri网上发生而不是在将其转换为a时发生Path
M. Justin'1

1
@HuguesFontenelle根据@SourceURI的文档,所得值将是的实例java.net.URI;加上您显示的地图是java.net.URI该类的属性。您确定它实际上是在设置地图,而不是地图URI吗?无论如何,这看起来像是数据URL,而不是文件URL。脚本的来源实际上是本地文件,而不是通过网络序列化的东西或类似的东西吗?在这种情况下,甚至没有相应的文件,这说明了为什么无法将其转换为Path
M. Justin

1
@HuguesFontenelle您如何运行脚本?根据对这个问题的回答(stackoverflow.com/questions/26240588/…),@SourceURI如果从Groovy控制台运行,则该方法不起作用,我已经在本地确认。当您直接从命令行运行脚本时会发生什么?例如groovy sourceUriTest.groovy,用sourceUriTest.groovy您的实际脚本文件替换“ ”?
M. Justin

1
我正在使用使用groovy的nextflow,我只是发现文件路径可供我使用workflow.scriptFile(或workflow. projectDir用于dir路径)。感谢您查看这个!
Hugues Fontenelle

79

您是正确的,new File(".").getCanonicalPath()不起作用。返回工作目录

获取脚本目录

scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent

获取脚本文件路径

scriptFile = getClass().protectionDomain.codeSource.location.path

1
有趣。它不符合我的预期。但这是由于我正在从gant运行gant脚本。所以codeSource实际上是gant所在的位置,而不是我的脚本所在的位置。
丹·伍德沃德

1
对我不起作用。 getClass().protectionDomain.codeSource返回null。我正在使用Groovy 2.0.1。
quux00 2014年

关于是否或者1.11,退货不工作是这样的:.gradle /缓存/ 1.11 /脚本/ build_189dc3r2nd588m3657jv5d36h7 ..
明斯克

2
@ quux00:尝试MyClassName.class.protectionDomain.codeSource代替(REF stackoverflow.com/questions/11747833/...
neu242

3
根据它的运行方式,我得到的是/groovy父目录还是正确的目录。那怎么办:getClass().getResource('/${yourScript}.groovy')假设您的脚本在
Christian Bongiorno,


1

对于gradle用户

我开始使用gradle时遇到相同的问题。我想通过远程Thrift编译器(我公司自定义)编译Thrift。

以下是我解决问题的方法:

task compileThrift {
doLast {
        def projectLocation = projectDir.getAbsolutePath(); // HERE is what you've been looking for.
        ssh.run {
            session(remotes.compilerServer) {
                // Delete existing thrift file.
                cleanGeneratedFiles()
                new File("$projectLocation/thrift/").eachFile() { f ->
                    def fileName=f.getName()
                    if(f.absolutePath.endsWith(".thrift")){
                        put from: f, into: "$compilerLocation/$fileName"
                    }
                }
                execute "mkdir -p $compilerLocation/gen-java"
                def compileResult = execute "bash $compilerLocation/genjar $serviceName", logging: 'stdout', pty: true
                assert compileResult.contains('SUCCESSFUL')
                get from: "$compilerLocation/$serviceName" + '.jar', into: "$projectLocation/libs/"
            }
        }
    }
}

1

另一种解决方案。即使您使用GrovyConsole运行脚本,它也可以完美运行

File getScriptFile(){
    new File(this.class.classLoader.getResourceLoader().loadGroovySource(this.class.name).toURI())
}

println getScriptFile()

0

解决方法:对我们来说,它运行在ANT环境中,并在Java环境属性(System.setProperty( "dirAncestor", "/foo" ))中存储了一些位置父级(知道子路径),我们可以通过Groovy的来访问目录祖先properties.get('dirAncestor')
也许这将对此处提到的某些情况有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.