Подтвердить что ты не робот

Имеет ли groovy простой способ получить имя файла без расширения?

Скажем, у меня есть что-то вроде этого:

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

Это печатает полное имя файла для каждого файла в каталоге test. Есть ли способ Groovy получить имя файла без какого-либо расширения? (Или вернусь в землю регулярного выражения?)

4b9b3361

Ответ 1

Я считаю, что самым лучшим способом было бы:

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

или с простым регулярным выражением:

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

также есть apache commons-io java lib для этих целей, от которых вы могли бы легко зависеть, если вы используете maven:

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

Ответ 2

Самый чистый способ.

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

Ответ 3

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
}

Ответ 4

Возможно, не так просто, как вы ожидали, но работаете:

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

Ответ 5

Как упоминалось в комментариях, где имя файла заканчивается, и начало расширения зависит от ситуации. В моей ситуации мне нужно было получить базовое имя (файл без пути и без расширения) следующих типов файлов: { foo.zip, bar/foo.tgz, foo.tar.gz} = > все должны создать "foo" как имя файла без расширения. (Большинство решений, учитывая foo.tar.gz, произведут foo.tar.)

Здесь одно (очевидное) решение, которое даст вам все до первого "."; возможно, вы можете получить все расширение в виде кусков или (в данном случае) в виде одного остатка (разделение имени файла на части 2). (Обратите внимание: хотя это не связано с задачей, я также удаляю этот путь, вызывая file.name.)

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

Ответ 6

Класс FilenameUtils, являющийся частью пакета apache commons io, имеет надежное решение. Пример использования:

import org.apache.commons.io.FilenameUtils

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

Это не способ groovy, но может быть полезен, если вам нужно поддерживать множество случаев с краями.

Ответ 7

Вы можете использовать регулярные выражения лучше. Функция, подобная следующей, выполнит трюк:

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
}

Ответ 8

Примечание

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

Некоторые из приведенных ниже решений (кроме тех, которые используются в Apache-библиотеке) для этого примера не работают - c:/test.me/firstfile

Если я попытаюсь найти расширение для записи выше, я получу ".me/firstfile" -: (

Лучшим подходом будет поиск последнего вхождения File.separator, если он присутствует, а затем поиск имени файла или расширения.

Примечание: (Ниже приведен небольшой трюк. Для Windows разделитель файлов - \. Но это специальный символ в регулярном выражении, поэтому, когда мы используем переменную, содержащую File.separator в регулярном выражении, мне нужно ее избежать. Вот почему я делаю это:

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"

Ответ 9

Самый простой способ:

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

Результат:

file.name.with.dots

Ответ 10

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