listConditionallyRecursive method

Stream<FileSystemEntity> listConditionallyRecursive({
  1. required bool recurseCondition(
    1. Directory directory
    ),
  2. bool followLinks = true,
})

Lists the sub-directories and files of this Directory similar to list.

However instead of just having a recursive parameter that decides whether to recurse into all or no subdirectories, a function recurseCondition can be given that can decide for a given directory whether to recurse into it or not. The contents of this directory are always listed and the function is not called with this as argument.

Implementation

Stream<FileSystemEntity> listConditionallyRecursive({
  required bool Function(Directory directory) recurseCondition,
  bool followLinks = true,
}) {
  Stream<FileSystemEntity> recurse(
    Directory directory,
    Set<String> visitedLinks,
  ) async* {
    await for (final entity in directory.list(followLinks: false)) {
      if (entity is File) {
        yield entity;
      } else if (entity is Directory) {
        yield entity;
        if (recurseCondition(entity)) {
          yield* recurse(entity, visitedLinks);
        }
      } else if (entity is Link) {
        if (!followLinks ||
            visitedLinks.contains(await entity.tryResolveSymbolicLinks())) {
          yield entity;
          break;
        }

        // We can ignore the link case here because
        // [FileSystemEntity.typeSync] resolves links by default.
        // ignore: exhaustive_cases
        switch (FileSystemEntity.typeSync(entity.path)) {
          case FileSystemEntityType.directory:
            final directory = Directory(entity.path);
            yield directory;
            if (recurseCondition(directory)) {
              yield* recurse(
                directory,
                {...visitedLinks, await entity.resolveSymbolicLinks()},
              );
            }
            break;
          case FileSystemEntityType.file:
            yield File(entity.path);
            break;
          case FileSystemEntityType.notFound:
            yield entity;
            break;
        }
      }
    }
  }

  return recurse(this, {});
}