web-dev-qa-db-ja.com

Javaでワイルドカード文字列に一致するファイルを見つける方法は?

これは本当に簡単なはずです。このような文字列がある場合:

../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"に自動解析するようであることは言うまでもありません「時間と手間がかかります...ミックスにファイル以外の引数がなかったことを嬉しく思います。)

133
Jason S

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)。

70
Misha

FileUtils from Apache commons-iolistFilesおよび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 を使用できます。

113
Vladimir

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));
    }
45
Vadzim

ワイルドカード文字列を正規表現に変換し、それを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));
27
Fabian Steeg

現時点では役に立たないかもしれませんが、JDK 7は、「その他のNIO機能」の一部として、グロブと正規表現のファイル名の一致を目的としています。

17

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")
);
17
Grzegorz Gajos

ワイルドカードライブラリは、globとregexの両方のファイル名のマッチングを効率的に行います。

http://code.google.com/p/wildcard/

実装は簡潔です-JARは12.9キロバイトです。

12
NateS

外部インポートを使用しない簡単な方法は、このメソッドを使用することです

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); 
                }
           }
     }    
}

10
Umair Aziz

別の回答に投稿されているように、ワイルドカードライブラリは、グロブと正規表現の両方のファイル名の一致に対して機能します。 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と比較的小さいです。

レビュアーへの注意:このライブラリに言及している既存の回答に上記を追加しようとしましたが、編集は拒否されました。これをコメントとして追加するのに十分な担当者もいません。もっと良い方法はありませんか...

6
Oliver Coleman

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で置き換える必要はありません。これはテストしていませんが、パターンとファイルフィルターは常に使用しています。

5
Anonymous

Glob Java7の場合: ファイルの検索 。 ( サンプル

Apacheフィルターは、既知のディレクトリ内のファイルを反復処理するために構築されています。ディレクトリでもワイルドカードを許可するには、「\」または「/」でパスを分割し、各部分で個別にフィルターを実行する必要があります。

3
Michael Myers

使用しないのは、次のようなことです:

File myRelativeDir = new File("../../foo");
String fullPath = myRelativeDir.getCanonicalPath();
Sting wildCard = fullPath + File.separator + "*.txt";

// now you have a fully qualified path

そうすれば、相対パスを心配する必要がなくなり、必要に応じてワイルドカードを使用できます。

0
Elijah

使用方法:

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
0
Tony
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);
0
Anatoliy Shuba

JDK FileVisitorインターフェースを実装します。以下に例を示します http://wilddiary.com/list-files-matching-a-naming-pattern-Java/

0
Drona