@ApiStatus.Experimental
  public static void copyRecursively(@NotNull Path from, @NotNull Path to, @Nullable Consumer<? super Path> callback) throws IOException {
    Files.walkFileTree(from, new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        if (callback != null) callback.accept(dir);
        Path copy = dir == from ? to : to.resolve(from.relativize(dir));
        createDirectories(copy);
        return FileVisitResult.CONTINUE;
      }

      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        if (callback != null) callback.accept(file);
        Path copy = file == from ? to : to.resolve(from.relativize(file));
        Files.copy(file, copy, LinkOption.NOFOLLOW_LINKS, StandardCopyOption.COPY_ATTRIBUTES);
        return FileVisitResult.CONTINUE;
      }
    });
  }
@ApiStatus.Experimental
  public static void copyRecursively(@NotNull Path from, @NotNull Path to, @Nullable Consumer<? super Path> callback)