これは本当に簡単なはずです。このような文字列がある場合:
../Test?/sample*.txt
次に、このパターンに一致するファイルのリストを取得する一般的に受け入れられている方法は何ですか? (たとえば、../Test1/sample22b.txt
および../Test4/sample-spiffy.txt
と一致する必要がありますが、../Test3/sample2.blah
または../Test44/sample2.txt
とは一致しません)
org.Apache.commons.io.filefilter.WildcardFileFilter
を見てみましたが、これは正しい獣のように見えますが、相対ディレクトリパスでファイルを見つけるためにそれを使用する方法がわかりません。
ワイルドカード構文を使用しているので、antのソースを見ることができると思いますが、ここではかなり明白な何かを見逃しているに違いありません。
(edit:上記の例は単なるサンプルです。実行時にワイルドカードを含む一般的なパスを解析する方法を探しています。 Java JREがmain(String []引数)の単純なワイルドカードを単一の引数から "save"に自動解析するようであることは言うまでもありません「時間と手間がかかります...ミックスにファイル以外の引数がなかったことを嬉しく思います。)
Apache AntのDirectoryScannerを検討してください。
DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.Java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();
Ant.jarを参照する必要があります(ant 1.7.1では〜1.3 MB)。
FileUtils
from Apache commons-io (listFiles
およびiterateFiles
メソッド)を試してください:
File dir = new File(".");
FileFilter fileFilter = new WildcardFileFilter("sample*.Java");
File[] files = dir.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
System.out.println(files[i]);
}
TestX
フォルダーの問題を解決するには、最初にフォルダーのリストを反復処理します。
File[] dirs = new File(".").listFiles(new WildcardFileFilter("Test*.Java");
for (int i=0; i<dirs.length; i++) {
File dir = dirs[i];
if (dir.isDirectory()) {
File[] files = dir.listFiles(new WildcardFileFilter("sample*.Java"));
}
}
かなり「ブルートフォース」ソリューションですが、正常に動作するはずです。これがニーズに合わない場合は、常に RegexFileFilter を使用できます。
Java 7 nioglobbing およびJava 8ラムダを使用したパターンによるファイルのリストの例を次に示します。
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
Paths.get(".."), "Test?/sample*.txt")) {
dirStream.forEach(path -> System.out.println(path));
}
または
PathMatcher pathMatcher = FileSystems.getDefault()
.getPathMatcher("regex:Test./sample\\w+\\.txt");
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
new File("..").toPath(), pathMatcher::matches)) {
dirStream.forEach(path -> System.out.println(path));
}
ワイルドカード文字列を正規表現に変換し、それをStringのmatches
メソッドで使用できます。あなたの例に従って:
String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");
これはあなたの例に役立ちます:
Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));
そして反例:
Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
現時点では役に立たないかもしれませんが、JDK 7は、「その他のNIO機能」の一部として、グロブと正規表現のファイル名の一致を目的としています。
Java 8以降では、Files#find
からJava.nio.file
メソッドを直接使用できます。
public static Stream<Path> find(Path start,
int maxDepth,
BiPredicate<Path, BasicFileAttributes> matcher,
FileVisitOption... options)
Files.find(startingPath,
Integer.MAX_VALUE,
(path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
ワイルドカードライブラリは、globとregexの両方のファイル名のマッチングを効率的に行います。
http://code.google.com/p/wildcard/
実装は簡潔です-JARは12.9キロバイトです。
外部インポートを使用しない簡単な方法は、このメソッドを使用することです
Billing_201208.csv、billing_201209.csv、billing_201210.csvという名前のcsvファイルを作成しましたが、正常に動作しているようです。
上記のファイルが存在する場合、出力は次のようになります
found billing_201208.csv
found billing_201209.csv
found billing_201210.csv
//インポートを使用-> import Java.io.File public static void main(String [] args){ String pathToScan = "。"; 文字列target_file; // fileThatYouWantToFilter File folderToScan = new File(pathToScan);
File[] listOfFiles = folderToScan.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
target_file = listOfFiles[i].getName();
if (target_file.startsWith("billing")
&& target_file.endsWith(".csv")) {
//You can add these files to fileList by using "list.add" here
System.out.println("found" + " " + target_file);
}
}
}
}
別の回答に投稿されているように、ワイルドカードライブラリは、グロブと正規表現の両方のファイル名の一致に対して機能します。 http://code.google.com/p/wildcard/
次のコードを使用して、* nixスタイルのファイルシステムで絶対および相対を含むグロブパターンに一致させました。
String filePattern = String baseDir = "./";
// If absolute path. TODO handle windows absolute path?
if (filePattern.charAt(0) == File.separatorChar) {
baseDir = File.separator;
filePattern = filePattern.substring(1);
}
Paths paths = new Paths(baseDir, filePattern);
List files = paths.getFiles();
私はこれを行うためにApache commons ioライブラリのFileUtils.listFilesメソッド(Vladimirの答えを参照)を取得しようとしましたが、成功しませんでした(一度に1つのディレクトリまたはファイルに一致するパターンしか処理できないことがわかりました) 。
さらに、ファイルシステム全体を検索せずに任意のユーザー指定の絶対型globパターンを処理するために正規表現フィルター(Fabianの回答を参照)を使用すると、最大の非正規表現/ globプレフィックスを決定するために、指定されたglobの前処理が必要になります。
もちろん、Java 7は要求された機能をうまく処理できますが、残念ながら今のところJava 6にこだわっています。このライブラリは、サイズが13.5kbと比較的小さいです。
レビュアーへの注意:このライブラリに言及している既存の回答に上記を追加しようとしましたが、編集は拒否されました。これをコメントとして追加するのに十分な担当者もいません。もっと良い方法はありませんか...
WildcardFileFilter
を使用できるはずです。 System.getProperty("user.dir")
を使用して作業ディレクトリを取得します。これを試して:
public static void main(String[] args) {
File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args));
//...
}
ワイルドカードフィルターが*
を使用すると仮定すると、[.*]
をJava.regex.Pattern
で置き換える必要はありません。これはテストしていませんが、パターンとファイルフィルターは常に使用しています。
Apacheフィルターは、既知のディレクトリ内のファイルを反復処理するために構築されています。ディレクトリでもワイルドカードを許可するには、「\
」または「/
」でパスを分割し、各部分で個別にフィルターを実行する必要があります。
使用しないのは、次のようなことです:
File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";
// now you have a fully qualified path
そうすれば、相対パスを心配する必要がなくなり、必要に応じてワイルドカードを使用できます。
使用方法:
public static boolean isFileMatchTargetFilePattern(final File f, final String targetPattern) {
String regex = targetPattern.replace(".", "\\."); //escape the dot first
regex = regex.replace("?", ".?").replace("*", ".*");
return f.getName().matches(regex);
}
jUnitテスト:
@Test
public void testIsFileMatchTargetFilePattern() {
String dir = "D:\\repository\\org\my\\modules\\mobile\\mobile-web\\b1605.0.1";
String[] regexPatterns = new String[] {"_*.repositories", "*.pom", "*-b1605.0.1*","*-b1605.0.1", "mobile*"};
File fDir = new File(dir);
File[] files = fDir.listFiles();
for (String regexPattern : regexPatterns) {
System.out.println("match pattern [" + regexPattern + "]:");
for (File file : files) {
System.out.println("\t" + file.getName() + " matches:" + FileUtils.isFileMatchTargetFilePattern(file, regexPattern));
}
}
}
出力:
match pattern [_*.repositories]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:true
match pattern [*.pom]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [*-b1605.0.1*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
match pattern [*-b1605.0.1]:
mobile-web-b1605.0.1.pom matches:false
mobile-web-b1605.0.1.war matches:false
_remote.repositories matches:false
match pattern [mobile*]:
mobile-web-b1605.0.1.pom matches:true
mobile-web-b1605.0.1.war matches:true
_remote.repositories matches:false
Path testPath = Paths.get("C:\");
Stream<Path> stream =
Files.find(testPath, 1,
(path, basicFileAttributes) -> {
File file = path.toFile();
return file.getName().endsWith(".Java");
});
// Print all files found
stream.forEach(System.out::println);
JDK FileVisitorインターフェースを実装します。以下に例を示します http://wilddiary.com/list-files-matching-a-naming-pattern-Java/