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

Я хочу просмотреть дерево каталогов со многими подкаталогами.Моя цель - распечатать все .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 Ответ

1 голос
/ 14 апреля 2019

Да, что-то не так с синтаксисом 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}");
...