Files
claude-werkzeuge/.vault-tools/verbrauch-auswertung/claudedata_wurzel.py
T
Pascal Michel 9e506ff588 Abgleich mit dem Vault-Stand 7f484f9
38 Datei(en) geändert.
Erzeugt von .vault-tools/auto-push/werkzeuge_spiegel.py.
2026-11-02 03:00:03 +01:00

100 lines
4.1 KiB
Python

"""Ordnet die Einträge direkt unter dem Datenordner von Claude Code ein: bekannte Ordner gegen zufällig benannte Temp-Ordner.
Ersteller: Pascal Michel
Erstellt: 2026-10-30
Doku: LIESMICH.md in diesem Ordner
Nur lesend. Gibt Anzahl, Größe, Alter und Endungsmuster aus, keine Dateiinhalte; die Strukturbeispiele
am Schluss nennen bis zu fünf Dateinamen je Ordner.
Was es nicht sieht: Ob ein Zufallsordner noch von einer laufenden Sitzung benutzt wird. Das Alter kommt
aus mtime, und die App fasst beim Neustart viele Dateien an (Harness-Erinnerung
transkript-usage-groesster-wert-je-nachricht). Vor jedem Löschen also laufende Sitzungen über die App
prüfen, nicht über dieses Skript.
Zufällig benannt heißt: 21 Zeichen aus [A-Za-z0-9_-] (nanoid-artig) und nicht in BEKANNT.
Aufruf: python -I -X utf8 claudedata_wurzel.py [Wurzel, Vorgabe D:\\ClaudeData]
"""
import collections
import datetime
import os
import re
import sys
import time
BEKANNT = {"claude", "config", "tmp", "umzug", "codex-review"}
MUSTER = re.compile(r"^[A-Za-z0-9_-]{21}$")
def groesse(p):
total = 0; anzahl = 0; namen = collections.Counter(); neueste = 0
for root, dirs, files in os.walk(p):
for f in files:
fp = os.path.join(root, f)
try:
st = os.stat(fp)
except OSError:
continue
total += st.st_size; anzahl += 1; neueste = max(neueste, st.st_mtime)
ext = os.path.splitext(f)[1].lower() or f[:20]
namen[ext] += 1
return total, anzahl, namen, neueste
def main(argv):
wurzel = argv[1] if len(argv) > 1 else r"D:\ClaudeData"
if not os.path.isdir(wurzel):
print(f"Wurzel fehlt: {wurzel}")
return 2
jetzt = time.time()
with os.scandir(wurzel) as it:
eintraege = list(it)
zufall = [e for e in eintraege if e.is_dir() and MUSTER.match(e.name) and e.name not in BEKANNT]
andere = [e for e in eintraege if e not in zufall]
print(f"Einträge gesamt: {len(eintraege)}; zufällig benannte Ordner: {len(zufall)}; andere: {len(andere)}")
print("\nAndere Einträge:")
for e in sorted(andere, key=lambda x: x.name):
try:
st = e.stat()
print(f" {'D' if e.is_dir() else 'F'} {e.name} mtime {datetime.datetime.fromtimestamp(st.st_mtime):%Y-%m-%d}")
except OSError:
print(" ?", e.name)
gesamt = 0; dateien = 0; alter = collections.Counter(); muster = collections.Counter(); tage_liste = []
topnamen = collections.Counter(); beispiele = {}
for e in zufall:
t, n, namen, neueste = groesse(e.path)
gesamt += t; dateien += n
try:
mt = e.stat().st_mtime
except OSError:
mt = neueste
tage = (jetzt - max(mt, neueste)) / 86400
tage_liste.append(tage)
stufe = "<1 Tag" if tage < 1 else "1-7 Tage" if tage < 7 else "7-30 Tage" if tage < 30 else ">30 Tage"
alter[stufe] += 1
sig = ",".join(f"{k}:{v}" for k, v in sorted(namen.items())[:4])
muster[sig] += 1
for k in namen:
topnamen[k] += 1
beispiele.setdefault(sig, e.name)
print(f"\nZufallsordner: {len(zufall)}, Dateien {dateien}, Größe {gesamt/1e6:.1f} MB")
print("Alter (nach jüngster Änderung):", dict(alter))
if tage_liste:
print(f"ältester {max(tage_liste):.0f} Tage, jüngster {min(tage_liste):.2f} Tage")
print("\nHäufigste Inhaltsmuster (Endung:Anzahl je Ordner):")
for sig, n in muster.most_common(12):
print(f" {n:5d} x {sig or '(leer)'} Beispiel: {beispiele[sig]}")
print("\nHäufigste Dateiendungen über alle Zufallsordner:", dict(topnamen.most_common(12)))
for sig, n in muster.most_common(3):
p = os.path.join(wurzel, beispiele[sig])
print(f"\nStruktur von {beispiele[sig]}:")
for root, dirs, files in os.walk(p):
tiefe = root[len(p):].count(os.sep)
if tiefe > 2:
continue
print(" " * tiefe + os.path.basename(root) + "/", f"({len(dirs)} Ordner, {len(files)} Dateien)", sorted(files)[:5])
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))