次のようなものがあるとします。
new File("test").eachFile() { file->
println file.getName()
}
これにより、ディレクトリ内のすべてのファイルの完全なファイル名が出力されますtest
。拡張子なしでファイル名を取得するGroovyの方法はありますか? (または、正規表現の土地に戻っていますか?)
次のようなものがあるとします。
new File("test").eachFile() { file->
println file.getName()
}
これにより、ディレクトリ内のすべてのファイルの完全なファイル名が出力されますtest
。拡張子なしでファイル名を取得するGroovyの方法はありますか? (または、正規表現の土地に戻っていますか?)
最もグルーヴィーな方法は次のとおりだと思います。
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)
最もクリーンな方法。
String fileWithoutExt = file.name.take(file.name.lastIndexOf('.'))
最も簡単な方法は次のとおりです。
'file.name.with.dots.tgz' - ~/\.\w+$/
結果は次のとおりです。
file.name.with.dots
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
}
apache commons io パッケージの一部である FilenameUtils クラスには、堅牢なソリューションがあります。使用例:
import org.apache.commons.io.FilenameUtils
String filename = '/tmp/hello-world.txt'
def fileWithoutExt = FilenameUtils.removeExtension(filename)
これはグルーヴィーな方法ではありませんが、多くのエッジ ケースをサポートする必要がある場合に役立ちます。
あなたが期待したほど簡単ではないかもしれませんが、うまくいきます:
new File("test").eachFile {
println it.name.lastIndexOf('.') >= 0 ?
it.name[0 .. it.name.lastIndexOf('.')-1] :
it.name
}
コメントで述べたように、ファイル名がどこで終わり、拡張子が始まるかは状況によって異なります。私の状況では、次の種類のファイルのベース名 (パスなし、拡張子なしのファイル) を取得する必要がありました:foo.zip
{ 、bar/foo.tgz
、foo.tar.gz
} => すべて " foo
" をファイル名 sans extension として生成する必要があります。(与えられたほとんどのソリューションは、foo.tar.gz
を生成しfoo.tar
ます。)
最初の「。」までのすべてを提供する1つの(明白な)ソリューションを次に示します。オプションで、拡張子全体を分割して取得するか、(この場合は) 残りの 1 つ (ファイル名を2
部分に分割) として取得できます。(注: 当面のタスクとは関係ありませんが、 を呼び出してパスも削除していますfile.name
。)
file=new File("temp/foo.tar.gz")
file.name.split("\\.", 2)[0] // => return "foo" at [0], and "tar.gz" at [1]
正規表現をより適切に使用できます。次のような関数はトリックを行います:
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/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"