File size: 3,241 Bytes
f43fd2b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import os
import sys

# --- Configuration ---
OUTPUT_FILENAME = "!combo.txt"
# Folders to skip to prevent massive/useless data bloat
BLACKLIST_DIRS = {".git", "__pycache__", ".ipynb_checkpoints", "node_modules", "venv", ".vscode"}
# --- End Configuration ---

def combine_all_recursive():
    """

    Recursively combines all files in the script's directory and all subdirectories

    into a single output file with relative path tags.

    """
    try:
        # Determine the script's own path
        if getattr(sys, 'frozen', False):
            script_full_path = os.path.abspath(sys.executable)
        else:
            script_full_path = os.path.abspath(__file__)

        script_dir = os.path.dirname(script_full_path)
        output_filepath = os.path.join(script_dir, OUTPUT_FILENAME)

        print(f"Scanning recursively in: {script_dir}")
        print(f"Output file: {output_filepath}")
        print("-" * 40)

        file_list = []

        # os.walk handles the recursion automatically
        for root, dirs, files in os.walk(script_dir):
            # Modify dirs in-place to skip blacklisted folders
            dirs[:] = [d for d in dirs if d not in BLACKLIST_DIRS]
            
            for filename in files:
                full_path = os.path.join(root, filename)
                
                # Exclude the script itself and the output file
                if (os.path.normpath(full_path) == os.path.normpath(script_full_path) or 
                    filename == OUTPUT_FILENAME):
                    continue
                
                # Store relative path for sorting and tagging
                rel_path = os.path.relpath(full_path, script_dir)
                file_list.append((rel_path, full_path))

        # Sort by relative path so the combo file is organized logically
        file_list.sort(key=lambda x: x[0])

        if not file_list:
            print("No files found to combine.")
            return

        print(f"Found {len(file_list)} files. Starting combination...")

        with open(output_filepath, 'w', encoding='utf-8', errors='replace') as outfile:
            outfile.write("```\n") # Opening wrapper

            for rel_path, full_path in file_list:
                print(f"Adding: {rel_path}")
                try:
                    outfile.write(f"<{rel_path}>\n")
                    with open(full_path, 'r', encoding='utf-8', errors='replace') as infile:
                        outfile.write(infile.read())
                    outfile.write(f"\n</{rel_path}>\n\n")
                except Exception as e:
                    outfile.write(f"ERROR READING FILE {rel_path}: {e}\n")
                    outfile.write(f"</{rel_path}>\n\n")

            outfile.write("```\n") # Closing wrapper

        print("-" * 40)
        print(f"SUCCESS! Combined {len(file_list)} files into '{OUTPUT_FILENAME}'")

    except Exception as e:
        print(f"CRITICAL ERROR: {e}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    combine_all_recursive()
    try:
        input("\nProcess complete. Press Enter to exit...")
    except EOFError:
        pass