0

I'm trying to get *.jar files in a specified directory (no recursing subdirectories), I think my code is no problem, but the results are incomprehensible, am I doing something wrong?

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;

public class Test {

    private static final PathMatcher JAR_FILE_MATCHER = FileSystems.getDefault().getPathMatcher("glob:*.jar");

    public static void main(String[] args) throws IOException {
        List<Path> list = new ArrayList<>();
        Files.walkFileTree(Path.of("E:/lib"), new SimpleFileVisitor<>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (JAR_FILE_MATCHER.matches(file)) list.add(file);
                else System.out.println("[mismatched] " + file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException e) {
                return FileVisitResult.CONTINUE;
            }
        });
        System.out.printf("Total: %d jar files found!%n", list.size());
    }

}
The output:
[mismatched] E:\lib\commons-lang3-3.12.0.jar
[mismatched] E:\lib\log4j-api-2.18.0.jar
[mismatched] E:\lib\log4j-core-2.18.0.jar
[mismatched] E:\lib\ojdbc6-12.1.0.1-atlassian-hosted.jar
[mismatched] E:\lib\spring-web-5.3.22.jar
Total: 0 jar files found!

What is a better way to scan a specified directory for jars?

Thanks in advance :)

Xi Minghui
  • 95
  • 1
  • 9

2 Answers2

1

The problem is PathMatcher that you defined.

private static final PathMatcher JAR_FILE_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**/*.jar");

will work because '**' matches any string, including sub-path (like E:/lib in you example) :)

Bart-del
  • 36
  • 5
1

You should use the find version for your case:

try (Stream<Path> s = Files.find(Path.of("E:/lib"),
                                 1 /* see below */, 
                                 (path, attrs) -> JAR_FILE_MATCHER.matches(file)
                                )) {
  var list = s.toList();
}

The 1 is the maximum depth: if you don't want to scan recursively, a value of 1 would avoid that.

The list is another alternative, although it also returns directories and filtering files do have a cost:

try (Stream<Path> s = Files.list(Path.of("E:/lib"))) {
  var list = s.filter(JAR_FILE_MATCHER::matches)
              .filter(Files::isRegularFile)
              .toList();
}
NoDataFound
  • 11,381
  • 33
  • 59