Jak znaleźć pliki pasujące do ciągu znaków wieloznacznych w Javie?

To powinno być naprawdę proste. Jeśli mam taki ciąg:

../Test?/sample*.txt

Więc jaki jest ogólnie akceptowany sposób na uzyskanie listy plików pasujących do tego wzorca? (np. powinno pasować ../Test1/sample22b.txt i ../Test4/sample-spiffy.txt, ale nie ../Test3/sample2.blah lub ../Test44/sample2.txt)

I ' ve taked a look at org.apache.commons.io.filefilter.WildcardFileFilter i wydaje się być właściwą bestią, ale nie jestem pewien, jak jej użyć do znajdowania plików w względnej ścieżce katalogu.

Przypuszczam, że mogę poszukać źródła dla ant, ponieważ używa składni wildcard, ale muszę być brakuje tu czegoś oczywistego.

(edit : powyższy przykład był tylko przykładowym przypadkiem. Szukam sposobu na parsowanie ścieżek ogólnych zawierających symbole wieloznaczne w czasie wykonywania. Domyśliłem się, jak to zrobić na podstawie sugestii mmyersa, ale to trochę irytujące. Nie wspominając już o tym, że JRE wydaje się automatycznie parsować proste symbole wieloznaczne w argumentach main(String []) z jednego argumentu, aby" zaoszczędzić " mi czasu i kłopotów... Cieszę się, że nie miałem argumentów Nie-plików w miksie.)

Author: Jason S, 2009-04-27

15 answers

Rozważmy DirectoryScanner z Apache Ant:

DirectoryScanner scanner = new DirectoryScanner();
scanner.setIncludes(new String[]{"**/*.java"});
scanner.setBasedir("C:/Temp");
scanner.setCaseSensitive(false);
scanner.scan();
String[] files = scanner.getIncludedFiles();
Musisz odwołać się do mrówki.jar (~1.3 MB dla ant 1.7.1).
 68
Author: Misha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-30 05:55:10

Spróbuj FileUtils from Apache commons-io (listFiles i iterateFiles metody):

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

Aby rozwiązać twój problem z folderami TestX, najpierw przejrzyj listę folderów:

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"));
   }
}
Dość "brutalna siła" rozwiązanie, ale powinno działać dobrze. Jeśli to nie odpowiada twoim potrzebom, zawsze możesz użyć RegexFileFilter .
 107
Author: Vladimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-06 02:01:22

Oto przykłady listingu plików według pattern powered by Java 7 nio globbing i Java 8 lambdy:

    try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(
            Paths.get(".."), "Test?/sample*.txt")) {
        dirStream.forEach(path -> System.out.println(path));
    }

Lub

    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));
    }
 37
Author: Vadzim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:59

Możesz przekonwertować łańcuch znaków wieloznacznych na wyrażenie regularne i używać go w metodzie matches. Idąc za twoim przykładem:

String original = "../Test?/sample*.txt";
String regex = original.replace("?", ".?").replace("*", ".*?");

To działa na twoje przykłady:

Assert.assertTrue("../Test1/sample22b.txt".matches(regex));
Assert.assertTrue("../Test4/sample-spiffy.txt".matches(regex));

I przeciw-przykłady:

Assert.assertTrue(!"../Test3/sample2.blah".matches(regex));
Assert.assertTrue(!"../Test44/sample2.txt".matches(regex));
 27
Author: Fabian Steeg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 19:04:00

Może Ci teraz nie pomóc, ale JDK 7 jest przeznaczony do dopasowania nazw plików glob i regex jako część "więcej funkcji NIO".

 17
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-31 21:42:00

Od Javy 8 można używać metody Files#find bezpośrednio z java.nio.file.

public static Stream<Path> find(Path start,
                                int maxDepth,
                                BiPredicate<Path, BasicFileAttributes> matcher,
                                FileVisitOption... options)

Przykładowe użycie

Files.find(startingPath,
           Integer.MAX_VALUE,
           (path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
 13
Author: Grzegorz Gajos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-29 14:23:35

Biblioteka wildcard sprawnie dopasowuje nazwy plików glob i regex:

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

Implementacja jest zwięzła -- jar ma tylko 12,9 kilobajtów.

 12
Author: NateS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-16 01:42:08

Prostym sposobem bez użycia zewnętrznego importu jest użycie tej metody

Utworzyłem pliki csv o nazwie billing_201208.csv, billing_201209.csv, billing_201210.csv i wygląda na to, że działa dobrze.

Wyjście będzie następujące, jeśli pliki wymienione powyżej istnieją

found billing_201208.csv
found billing_201209.csv
found billing_201210.csv

    //Use Import ->import java.io.File
        public static void main(String[] args) {
        String pathToScan = ".";
        String 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); 
                }
           }
     }    
}

 9
Author: Umair Aziz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-21 02:34:20

Jak napisano w innej odpowiedzi, biblioteka wildcard działa zarówno dla dopasowania nazw plików glob i regex: http://code.google.com/p/wildcard/

Użyłem następującego kodu, aby dopasować wzorce globu, w tym absolutne i względne na systemach plików *nix style:

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();
Spędziłem trochę czasu próbując zdobyć pliki.listFiles metody w Apache commons io library (patrz odpowiedź Vladimira) zrobić to, ale nie odniósł sukcesu (zdaję sobie sprawę teraz/myślę, że może obsłużyć tylko dopasowanie wzorca jeden katalog lub plik na raz).

Dodatkowo, użycie filtrów regex (zobacz odpowiedź Fabiana) do przetwarzania dowolnych dostarczonych przez użytkownika wzorców glob typu absolutnego bez przeszukiwania całego systemu plików wymagałoby pewnego wstępnego przetwarzania dostarczonego globu w celu określenia największego przedrostka non-regex/glob.

Oczywiście Java 7 może dobrze obsługiwać żądaną funkcjonalność, ale niestety utknąłem na razie z Javą 6. Biblioteka jest stosunkowo niewielka w 13,5 kb w rozmiar.

Uwaga dla recenzentów: próbowałem dodać powyższe do istniejącej odpowiedzi wymieniającej tę bibliotekę, ale edycja została odrzucona. Ja też nie mam dość reputacji, żeby dodać to jako komentarz. Nie ma lepszego sposobu...

 6
Author: Oliver Coleman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-01 00:11:53

Powinieneś być w stanie użyć WildcardFileFilter. Wystarczy użyć System.getProperty("user.dir"), aby uzyskać katalog roboczy. Spróbuj tego:

public static void main(String[] args) {
File[] files = (new File(System.getProperty("user.dir"))).listFiles(new WildcardFileFilter(args));
//...
}

Nie należy zastępować * przez [.*], zakładając, że filtr wieloznaczny używa java.regex.Pattern. Nie testowałem tego, ale ciągle używam szablonów i filtrów plików.

 5
Author: Anonymous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-08 04:27:44
 4
Author: 卢声远 Shengyuan Lu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-03 13:02:33

Filtr Apache jest zbudowany do iteracji plików w znanym katalogu. Aby zezwolić na symbole wieloznaczne również w katalogu, musisz podzielić ścieżkę na '\ ' LUB '/ ' i wykonać filtr na każdej części osobno.

 3
Author: Michael Myers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 17:02:49

Dlaczego nie użyć zrób coś takiego:

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

// now you have a fully qualified path

Wtedy nie będziesz musiał martwić się o ścieżki względne i możesz zrobić wildcarding w razie potrzeby.

 0
Author: Elijah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 17:07:07

Zaimplementuj interfejs JDK FileVisitor. Oto przykład http://wilddiary.com/list-files-matching-a-naming-pattern-java/

 0
Author: Drona,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-16 15:36:40

Metoda Util:

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

    }

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

Wyjście:

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
Author: Tony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-23 19:37:40