[java] Java에서 와일드 카드 문자열과 일치하는 파일을 찾는 방법은 무엇입니까?

이것은 정말 간단해야합니다. 다음과 같은 문자열이있는 경우 :

../Test?/sample*.txt

그렇다면이 패턴과 일치하는 파일 목록을 얻는 데 일반적으로 허용되는 방법은 무엇입니까? (예를 들어,이 일치해야 ../Test1/sample22b.txt하고 ../Test4/sample-spiffy.txt있지만 ../Test3/sample2.blah../Test44/sample2.txt)

살펴본 org.apache.commons.io.filefilter.WildcardFileFilter결과 올바른 짐승처럼 보이지만 상대 디렉토리 경로에서 파일을 찾는 데 어떻게 사용하는지 잘 모르겠습니다.

와일드 카드 구문을 사용하기 때문에 개미의 소스를 볼 수 있다고 생각하지만 여기에 분명한 것이 빠져 있어야합니다.

( 편집 : 위의 예제는 샘플 사례 일뿐입니다. 런타임에 와일드 카드가 포함 된 일반 경로를 구문 분석하는 방법을 찾고 있습니다 .mmyers의 제안을 기반으로하는 방법을 알아 냈지만 성가신 종류입니다. Java JRE는 단일 인수에서 main (String [] arguments)의 간단한 와일드 카드를 자동 구문 분석하여 시간과 번거 로움을 “저장”하는 것 같습니다 … 파일에 인수가 아닌 인수가 없었기 때문에 기쁩니다. 혼합.)



답변

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.3MB).


답변

Apache commons-io ( 및 메소드) FileUtils에서 시도하십시오 .listFilesiterateFiles

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 nio globbing 및 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));


답변

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


답변

지금 당장 도움이되지는 않지만 JDK 7은 “More NIO Features”의 일부로 glob 및 regex 파일 이름이 일치하도록 고안되었습니다.


답변

와일드 카드 라이브러리는 glob 및 regex 파일 이름 일치를 효율적으로 수행합니다.

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

구현은 간결합니다. JAR은 12.9 킬로바이트에 불과합니다.