Ever felt like you have to provide your file structure to ChatGPT or Claude so that they can better understand and help you in your project? Well, I used this script to do it for one of my recent projects and helped me to not overexplain every detail to the AI and help it understand where all I need to apply changes.
import os
import fnmatch
def print_file_structure(root_dir, exclude_dirs=None, exclude_files=None, save_to_file=False, output_filename="file_structure.txt", prefix="", file=None):
"""
Prints the file structure of a directory, excluding specified folders and files, and optionally saves it to a file.
Parameters:
- root_dir (str): The root directory to scan.
- exclude_dirs (list): List of folder names to exclude.
- exclude_files (list): List of file patterns to exclude (e.g., "*.py").
- save_to_file (bool): Whether to save the output to a file.
- output_filename (str): The filename to save the output if save_to_file is True.
- prefix (str): The prefix string for the current depth level.
- file (file object): File object used for recursive writing to file if save_to_file is True.
"""
if exclude_dirs is None:
exclude_dirs = []
if exclude_files is None:
exclude_files = []
# Open the file for writing if save_to_file is True and it's the first call
if save_to_file and file is None:
file = open(output_filename, "w", encoding="utf-8") # Set encoding to UTF-8
try:
# Get a list of items in the directory, excluding specified folders
items = os.listdir(root_dir)
items = [item for item in items if item not in exclude_dirs]
for i, item in enumerate(items):
item_path = os.path.join(root_dir, item)
is_last = i == len(items) - 1
# Choose the branch character based on whether it's the last item
branch = "└── " if is_last else "├── "
next_prefix = " " if is_last else "│ "
# Exclude files based on patterns in exclude_files
if os.path.isfile(item_path) and any(fnmatch.fnmatch(item, pattern) for pattern in exclude_files):
continue # Skip excluded files
# Prepare line for directory or file
line = f"{prefix}{branch}📁 {item}" if os.path.isdir(item_path) else f"{prefix}{branch}📄 {item}"
print(line) # Print to console
# Write to file if saving
if save_to_file:
file.write(line + "\n")
# Recurse into directories with updated prefix
if os.path.isdir(item_path):
print_file_structure(item_path, exclude_dirs, exclude_files, save_to_file, output_filename, prefix + next_prefix, file)
except PermissionError:
line = f"{prefix}🚫 [Permission Denied] {root_dir}"
print(line)
if save_to_file:
file.write(line + "\n")
finally:
# Close the file after the initial call finishes if saving to file
if file and prefix == "":
file.close()
# Usage
root_directory = "."
excluded_folders = [".next", "node_modules", "__pycache__", ".git"]
excluded_files = ["*.py"]
print_file_structure(root_directory, excluded_folders, excluded_files, save_to_file=True, output_filename="project_structure.txt")