Electrons_Ahoy
Electrons_Ahoy

Reputation: 38613

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

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 land?)

Upvotes: 61

Views: 123094

Answers (10)

Marco
Marco

Reputation: 1

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

Upvotes: -3

librucha
librucha

Reputation: 685

Simplest way is:

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

Result is:

file.name.with.dots

Upvotes: 16

Pier
Pier

Reputation: 531

The cleanest way.

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

Upvotes: 40

Sajumon Joseph
Sajumon Joseph

Reputation: 31

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"

Upvotes: 0

Jay Prall
Jay Prall

Reputation: 5465

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.

Upvotes: 8

michael
michael

Reputation: 9779

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]

Upvotes: 2

Mauro Zallocco
Mauro Zallocco

Reputation: 306

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
}

Upvotes: 9

Nikita Volkov
Nikita Volkov

Reputation: 43310

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)

Upvotes: 56

Alex
Alex

Reputation: 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
}

Upvotes: 0

Alexander Egger
Alexander Egger

Reputation: 5300

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 
  }

Upvotes: 5

Related Questions