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