开发者

Does groovy have an easy way to get a filename without the extension?

开发者 https://www.devze.com 2022-12-08 08:05 出处:网络
Say I have something like this: new File(\"test\").eachFile() { file-> println file.getName() } This prints the full filename of every file in the test directory.Is there a Groovy way to get the

Say I have something like this:

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

This prints the full filename of every file in the test directory. Is there a Groovy way to get the filename without any extension? (Or am I back in regex la开发者_开发问答nd?)


I believe the grooviest way would be:

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

or with a simple regexp:

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

also there's an apache commons-io java lib for that kinda purposes, which you could easily depend on if you use maven:

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


The cleanest way.

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


Simplest way is:

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

Result is:

file.name.with.dots


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

This works well for file names like: foo, foo.bar

But if you have a file foo.bar.jar, then the above code prints out: foo If you want it to print out foo.bar instead, then the following code achieves that.

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


The FilenameUtils class, which is part of the apache commons io package, has a robust solution. Example usage:

import org.apache.commons.io.FilenameUtils

String filename = '/tmp/hello-world.txt'
def fileWithoutExt = FilenameUtils.removeExtension(filename)

This isn't the groovy way, but might be helpful if you need to support lots of edge cases.


Maybe not as easy as you expected but working:

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


As mentioned in comments, where a filename ends & an extension begins depends on the situation. In my situation, I needed to get the basename (file without path, and without extension) of the following types of files: { foo.zip, bar/foo.tgz, foo.tar.gz } => all need to produce "foo" as the filename sans extension. (Most solutions, given foo.tar.gz would produce foo.tar.)

Here's one (obvious) solution that will give you everything up to the first "."; optionally, you can get the entire extension either in pieces or (in this case) as a single remainder (splitting the filename into 2 parts). (Note: although unrelated to the task at hand, I'm also removing the path as well, by calling file.name.)

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


You can use regular expressions better. A function like the following would do the trick:

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
}


Note

import java.io.File;

def fileNames    = [ "/a/b.c/first.txt", 
                     "/b/c/second",
                     "c:\\a\\b.c\\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}" 
}

Some of the below solutions (except the one using apache library) doesn't work for this example - c:/test.me/firstfile

If I try to find an extension for above entry, I will get ".me/firstfile" - :(

Better approach will be to find the last occurrence of File.separator if present and then look for filename or extension.

Note: (There is a little trick happens below. For Windows, the file separator is \. But this is a special character in regular expression and so when we use a variable containing the File.separator in the regular expression, I have to escape it. That is why I do this:

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

Hope it makes sense :)

Try this out:

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"


// 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()
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号