SimpleFileVisitor для обхода дерева каталогов, чтобы найти все.txt файлы, кроме двух подкаталогов

Я хочу пройти через дерево каталогов со многими подкаталогами. Моя цель - распечатать все.txt файлы, кроме тех, которые находятся в подкаталогах subdir и anotherdir. Я могу добиться этого с помощью приведенного ниже кода.

public static void main(String[] args) throws IOException {
    Path path = Paths.get("C:\\Users\\bhapanda\\Documents\\target");
    Files.walkFileTree(path, new Search());
}

private static final class Search extends SimpleFileVisitor<Path> {

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**\\subdir");
        PathMatcher pm1 = FileSystems.getDefault().getPathMatcher("glob:**\\anotherdir");
        if (pm.matches(dir) || pm1.matches(dir)) {
            System.out.println("matching dir found. skipping it");
            return FileVisitResult.SKIP_SUBTREE;
        } else {
            return FileVisitResult.CONTINUE;
        }
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:*.txt");
        if (pm.matches(file.getFileName())) {
            System.out.println(file);
        }
        return FileVisitResult.CONTINUE;
    }
}

Но когда я пытаюсь объединить pm и pm1 PathMatchers с приведенным ниже кодом, это не работает.

PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**\\{subdir,anotherdir}");
if (pm.matches(dir)) {
            System.out.println("matching dir found. skipping it");
            return FileVisitResult.SKIP_SUBTREE;
        } else {
            return FileVisitResult.CONTINUE;
        }
    }

Что-то не так с синтаксисом glob?

1 ответ

Да, что-то не так с синтаксисом glob. Вам нужно удвоить каждую обратную косую черту, чтобы они оставались после обратной косой черты в ваших шаблонах глобуса.

Первый матчер:

PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**\\subdir");

не соответствует пути, заканчивающемуся на \subdir, Скорее, двойная косая черта становится одиночной косой чертой в шаблоне глобуса, что означает, что 's' экранируется. А так как экранированные 's' это просто 's', это сопоставление эквивалентно:

PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**subdir");

Это означает, что он будет соответствовать любому пути, оканчивающемуся на subdir, Так что это будет соответствовать пути xxx\subdir, но также будет соответствовать пути xxx\xxxsubdir а также xxxsubdir,

Комбинированный матчер:

PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**\\{subdir,anotherdir}");

имеет ту же проблему. В этом случае избегается символ "{". В шаблоне glob это означает трактовать '{' как буквальный символ, а не как начало группы шаблонов. Таким образом, этот матч не будет соответствовать пути xxx\subdir, но это будет соответствовать пути xxx{subdir,anotherdir},

Эти два сопоставителя будут делать то, что предназначено:

PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**\\\\subdir");
PathMatcher pm = FileSystems.getDefault().getPathMatcher("glob:**\\\\{subdir,anotherdir}");
Другие вопросы по тегам