Skip to content

Instantly share code, notes, and snippets.

@anjoismysign
Created December 19, 2025 05:35
Show Gist options
  • Select an option

  • Save anjoismysign/76a86d389500f2a6959e8e1fbb514cb3 to your computer and use it in GitHub Desktop.

Select an option

Save anjoismysign/76a86d389500f2a6959e8e1fbb514cb3 to your computer and use it in GitHub Desktop.
Java ProjectTreeGenerator (MIT License)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ProjectTreeGenerator {
public static final String LAST_CONNECTOR = "└── ";
public static final String NOT_LAST_CONNECTOR = "├── ";
public static final String LAST_CHILD_PREFIX = " ";
public static final String NOT_LAST_CHILD_PREFIX = "│ ";
public static String generate(String rootPathString, int maxDepth) {
Path rootPath = Paths.get(rootPathString).toAbsolutePath().normalize();
// Define common exclusions: "build", "target", ".git", ".gradle", etc.
Predicate<Path> defaultExclusions = path -> {
String name = path.getFileName().toString();
return name.equals("build") ||
name.equals("target") ||
name.equals(".git") ||
name.equals(".gradle") ||
name.equals(".idea") ||
name.endsWith(".iml")||
name.endsWith(".DS_Store")||
name.endsWith(".vscode");
};
StringBuilder builder = new StringBuilder();
generateRecursive(rootPath, defaultExclusions, maxDepth, 0, "", builder);
String text = builder.toString();
return text.substring(0, text.length() - 1);
}
private static void generateRecursive(
Path currentDir,
Predicate<Path> isExcluded,
int maxDepth,
int currentDepth,
String prefix,
StringBuilder result
) {
if (currentDepth >= maxDepth) {
return;
}
try (Stream<Path> stream = Files.list(currentDir)) {
List<Path> entries = stream
.filter(path -> !isExcluded.test(path)) // IGNORE "build" here
.sorted(Comparator.comparing((Path p) -> !Files.isDirectory(p))
.thenComparing(p -> p.getFileName().toString().toLowerCase()))
.collect(Collectors.toList());
for (int index = 0; index < entries.size(); index++) {
Path entry = entries.get(index);
boolean isLast = (index == entries.size() - 1);
boolean isDirectory = Files.isDirectory(entry);
String connector = isLast ? LAST_CONNECTOR : NOT_LAST_CONNECTOR;
result.append(prefix).append(connector).append(entry.getFileName()).append("\n");
if (isDirectory) {
String childPrefix = prefix + (isLast ? LAST_CHILD_PREFIX : NOT_LAST_CHILD_PREFIX);
generateRecursive(entry, isExcluded, maxDepth, currentDepth + 1, childPrefix, result);
}
}
} catch (IOException e) {
// Silently skip directories that can't be read (system folders)
}
}
public static void main(String[] args) {
//Generating a tree from current directory with 15 maxDepth
String tree = ProjectTreeGenerator.generate(".", 15);
System.out.println("# Project structure");
System.out.println(tree);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment