groovy是否有一个简单的方法来获得没有扩展名的文件名?

说我有这样的事情:

new File("test").eachFile() { file-> println file.getName() } 

这将打印test目录中每个文件的完整文件名。 有Groovy的方式来获得没有任何扩展名的文件名? (或者我回到正则expression式的土地?)

我相信最古怪的方式是:

 file.name.lastIndexOf('.').with {it != -1 ? file.name[0..<it] : file.name} 

或者用一个简单的正则expression式:

 file.name.replaceFirst(~/\.[^\.]+$/, '') 

还有一个Apache的commons-io java lib用于那种目的,如果你使用maven,你可以很容易地依赖它:

 org.apache.commons.io.FilenameUtils.getBaseName(file.name) 

最干净的方式。

String fileWithoutExt = file.name.take(file.name.lastIndexOf('.'))

 new File("test").eachFile() { file-> println file.getName().split("\\.")[0] } 

这适用于像foo,foo.bar这样的文件名

但是,如果你有一个文件foo.bar.jar,那么上面的代码打印出来:foo如果你想它打印出foo.bar,那么下面的代码实现了。

 new File("test").eachFile() { file-> def names = (file.name.split("\\.") def name = names.size() > 1 ? (names - names[-1]).join('.') : names[0] println name } 

也许不如你预期的那么容易,但工作:

 new File("test").eachFile { println it.name.lastIndexOf('.') >= 0 ? it.name[0 .. it.name.lastIndexOf('.')-1] : it.name } 

正如评论中提到的那样,文件名结束和扩展开始取决于情况。 在我的情况下,我需要得到以下types的文件的基本名称(文件没有path,没有扩展名):{ foo.zipbar/foo.tgzfoo.tar.gz } =>所有需要产生“ foo “作为文件名无扩展名。 (大多数解决scheme,给foo.tar.gz会产生foo.tar 。)

这里有一个(显而易见的)解决scheme,可以为您提供一切。“ 可选地,您可以将整个扩展名作为单个剩余部分(将文件名拆分为2部分)。 (注意:虽然与手边的任务无关,但我也通过调用file.name去除path)。

 file=new File("temp/foo.tar.gz") file.name.split("\\.", 2)[0] // => return "foo" at [0], and "tar.gz" at [1] 

FilenameUtils类是apache commons io包的一部分,具有强大的解决scheme。 用法示例:

 import org.apache.commons.io.FilenameUtils String filename = '/tmp/hello-world.txt' def fileWithoutExt = FilenameUtils.removeExtension(filename) 

这不是常规的方式,但如果您需要支持大量的边缘案例,可能会有所帮助。

您可以更好地使用正则expression式。 像下面这样的函数可以做到这一点:

 def getExtensionFromFilename(filename) { def returned_value = "" m = (filename =~ /(\.[^\.]*)$/) if (m.size()>0) returned_value = ((m[0][0].size()>0) ? m[0][0].substring(1).trim().toLowerCase() : ""); return returned_value } 

注意

 import java.io.File; def fileNames = [ "/a/bc/first.txt", "/b/c/second", "c:\\a\\bc\\third...", "c:\\a\b\\c\\.text" ] def fileSeparator = ""; fileNames.each { // You can keep the below code outside of this loop. Since my example // contains both windows and unix file structure, I am doing this inside the loop. fileSeparator= "\\" + File.separator; if (!it.contains(File.separator)) { fileSeparator = "\\/" } println "File extension is : ${it.find(/((?<=\.)[^\.${fileSeparator}]+)$/)}" it = it.replaceAll(/(\.([^\.${fileSeparator}]+)?)$/,"") println "Filename is ${it}" } 

下面的一些解决scheme(除了使用apache库的解决scheme)不适用于这个例子 – c:/test.me/firstfile

如果我试图find以上条目的扩展名,我会得到“.me / firstfile” – 🙁

更好的方法是find最后一次出现的File.separator(如果存在),然后查找文件名或扩展名。

注意:(下面是一些小技巧,对于Windows,文件分隔符是\,但这是正则expression式中的一个特殊字符,所以当我们在正则expression式中使用包含File.separator的variables时,我必须转义这就是为什么我这样做:

 def fileSeparator= "\\" + File.separator; 

希望它是有道理的:)

试试这个:

 import java.io.File; String strFilename = "C:\\first.1\\second.txt"; // Few other flavors // strFilename = "/dd/dddd/2.dd/dio/dkljlds.dd" def fileSeparator= "\\" + File.separator; if (!strFilename.contains(File.separator)) { fileSeparator = "\\/" } def fileExtension = ""; (strFilename =~ /((?<=\.)[^\.${fileSeparator}]+)$/).each { match, extension -> fileExtension = extension } println "Extension is:$fileExtension" 

最简单的方法是:

 'file.name.with.dots.tgz' - ~/\.\w+$/​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ 

结果是:

 file.name.with.dots 
 // Create an instance of a file (note the path is several levels deep) File file = new File('/tmp/whatever/certificate.crt') // To get the single fileName without the path (but with EXTENSION! so not answering the question of the author. Sorry for that...) String fileName = file.parentFile.toURI().relativize(file.toURI()).getPath()