Files
claude-regelwerk/AI/Regelwerk/windows-shell.md
T
Pascal MichelandClaude Opus 5 13213ea0ac Automatischer Push: 46 Datei(en) geändert
- .claude/agents/planer.md
- .claude/settings.json
- .claude/workflows/executer-welle.js
- .claude/workflows/plankritik.js
- .claude/workflows/planung.js
- .claude/workflows/quorum.js
- .claude/workflows/verbrauch.js
- .claude/workflows/welle-mit-pruefung.js
- .vault-tools/shell-wache/ENTWURF.md
- .vault-tools/shell-wache/docs/code/shell_wache.md
- .vault-tools/shell-wache/docs/plans/2026-10-30-shell-wache/00-uebersicht.md
- .vault-tools/shell-wache/docs/plans/2026-10-30-shell-wache/task-01-shell-wache.md
- … und 34 weitere

Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-31 03:00:01 +01:00

6.6 KiB

type, title, status, summary, tags, created, updated
type title status summary tags created updated
resource Skripte und Shellbefehle unter Windows reference Verbindliche Regeln für Befehle und Skripte auf Pascals Windows-Maschine: welche Shell, welches Python, Kodierung, Zeilenenden, Quoting-Schichten, WSL und ssh.
regelwerk
windows
werkzeuge
2026-09-13 2026-10-30

Skripte und Shellbefehle unter Windows

Angeordnet am 2026-09-13. Laden, sobald du auf dieser Maschine ein Skript schreibst oder einen Shellbefehl ausführst, der mehr als ein einfaches Lesen ist. Die Regeln haben eins gemeinsam: Wer sie verletzt, bekommt fast nie eine Fehlermeldung, sondern ein plausibles falsches Ergebnis.

Die Fallgeschichten stehen im Harness-Gedächtnis. Der Name der Erinnerung steht jeweils in Klammern.

Welche Shell, welches Python

  • Nie implizit bash aufrufen, weder aus Python noch aus PowerShell. Windows sucht einen Programmnamen ohne Pfad zuerst in System32. Dort liegt der WSL-Starter, und seit dem 2026-09-03 startet er die Debian-Distribution statt der Git-Bash. Git-Bash sprichst du mit vollem Pfad an: C:\Program Files\Git\bin\bash.exe, nicht …\usr\bin\, weil der seine Coreutils nicht findet. WSL sprichst du mit wsl -d <Distro> an. shutil.which("bash") taugt nicht als Prüfung. (bash-startet-unter-windows-den-wsl-stub)
  • python, nicht python3. python3 ist hier der Microsoft-Store-Stub.
  • PYTHONIOENCODING=utf-8 vor jedem Python-Aufruf, der Umlaute oder Sonderzeichen ausgibt. Die Konsole fährt cp1252, und ohne die Variable bricht ein Skript mit UnicodeEncodeError ab oder zerlegt die Ausgabe.
    • ⚠ Mit python -I wirkt die Variable nicht: -I schließt -E ein und ignoriert alle PYTHON*-Variablen. Dann python -I -X utf8. Das trifft auch PYTHONDONTWRITEBYTECODE: Soll kein .pyc im Projekt landen, zusätzlich -B. (python-isoliert-ignoriert-pythonioencoding)

Skripte mit Prosa, Regex oder Backslashes

  • Als Datei im Scratchpad anlegen, nie als Heredoc und nie per python -. Jede Zeichenketten-Schicht frisst Backslashes, und aus einem Regex für „Backslash plus Pipe“ wird so eines, das alles trifft. (backslash-frisst-sich-durch-zwei-schichten)
  • Jeder Prosa-String in Python wird dreifach quotiert, auch einzeilige. Im Vault schließen deutsche Anführungszeichen mit einem geraden ", und das beendet in Python sonst den String. Vor dem Lauf python -m py_compile datei.py. (python-heredoc-bricht-an-anfuehrungszeichen)
  • Kein sed für Muster mit \|, \( oder \{.
  • Nach jeder Ersetzung die geänderte Stelle ausgeben, nicht nur den Exit-Code prüfen. Passt die Trefferzahl nicht zur Erwartung, ist das Muster kaputt.
  • Keinen Commit in dieselbe Befehlszeile hinter ein Skript hängen, dessen Ergebnis er beschreibt.

PowerShell 5.1

  • Eine .ps1 mit Nicht-ASCII-Zeichen bekommt eine UTF-8-BOM. Ohne BOM liest PowerShell 5.1 die Datei als ANSI. Bash-Skripte bekommen nie eine BOM, sie bricht die Shebang-Zeile. (powershell-liest-utf8-ohne-bom-als-ansi)
  • Wer nach Nicht-ASCII-Zeichen sucht, dekodiert die Datei ausdrücklich als UTF-8 und gibt Codepunkte aus (U+00B7), nicht die Zeichen. Select-String mit Umlaut-Regex trifft über BOM-lose Dateien nie, und die Konsole stellt auch korrekte Zeichen als Fragezeichen dar.
  • return ,$wert, wenn eine Funktion ein Feld zurückgeben kann. Ohne das Komma zerfällt ein byte[] in Einzelbytes. Das Komma bekommt einen Kommentar, sonst vereinfacht es jemand weg.
  • .Contains() statt -like, wenn das Muster einen Backtick, *, ? oder [ enthält.
  • Um native Aufrufe, deren Exit-Code entscheidet, $ErrorActionPreference lokal auf Continue setzen und im finally zurücksetzen. Unter Stop wirft 2>&1 schon bei harmlosem stderr-Text, auch wenn der Prozess mit Exit-Code 0 endet. (native-stderr-unter-erroractionpreference-stop)

Zeilenenden

Nie mit grep auf \r prüfen. Die Git-Bash übersetzt beim Lesen \r\n zu \n, das Ergebnis 0 belegt also kein LF. Belastbar sind tr -cd '\r' < datei | wc -c (0 heißt LF), od -c datei | head, file datei und git ls-files --eol datei. (grep-cr-in-git-bash-ist-blind)

WSL und entfernte Hosts

  • wsl -d <Distro> -- bash -lc '…' expandiert jedes $ schon auf der Windows-Seite, auch in einfachen Anführungszeichen. Pfade schreibst du deshalb literal, Exit-Codes gibst du im WSL-Teil selbst aus, oder du legst das Skript als Datei ab. (wsl-bash-lc-expandiert-windowsseitig)
  • Befehle an entfernte Linux-Hosts laufen als LF-Datei über stdin: cmd /c "ssh.exe <optionen> root@<host> bash -s < datei.sh". Verschachtelte Anführungszeichen kommen aus PowerShell nicht heil an. (ssh-aus-powershell-als-datei-ueber-stdin)
  • SSH_ASKPASS ohne Leerzeichen im Pfad, und vor der ersten Verbindung einmal probeweise starten. Windows-OpenSSH startet askpass per posix_spawnp; scheitert das an einem Leerzeichen, schickt ssh ein leeres Passwort und erzeugt einen Fehlversuch am Ziel, der eine Login-Sperre füttert. UserKnownHostsFile ohne ~ im Pfad: ssh expandiert die Tilde auch im Windows-Kurzpfad (C:\Users\NAME~1\…) und schreibt dann still keinen Hostschlüssel; Langpfad mit / in Anführungszeichen nehmen. (ssh-aus-powershell-als-datei-ueber-stdin)
  • In einem über stdin gestarteten Skript liest kein Befehl stdin. Das heißt ssh -n, ausearch … < /dev/null, nie | sh. Prüfskripte legst du erst nach /tmp und startest sie dann. (pruefskript-liest-stdin)
  • pkill nur mit PID oder Sitzungspräfix, nie pkill -f mit einem allgemeinen Muster (Pascal, 2026-10-30). Ein Muster trifft auch die Prozesse anderer Sitzungen in derselben WSL-Distribution oder auf demselben Host; so beendete pkill -f Mutantenläufe einer parallelen Sitzung (Workflow-Review 2026-10-30, S-13). Merk dir die PID beim Start ($!) und beende nur sie. Geht das nicht, enthält das Muster einen Namen, den nur deine Sitzung vergibt, etwa den Ordner ihrer Kopie.

Geheimnisse in Ausgaben

Aus Umgebungsvariablen, Settings-Dateien und Transkripten gibst du nie Werte aus, nur Schlüssel, Zeilennummern und Längen. Das gilt auch für jeden Auftrag an einen Subagenten, der solche Dateien berührt. Ein Agent, der eine Datei mit Klartext-Token liest, kopiert das Token in sein Transkript. Findest du ein Geheimnis im Klartext, empfiehlst du zuerst die Rotation. (umgebungsvariablen-nur-als-laenge-ausgeben, settings-dateien-nicht-roh-an-subagenten)

Referenzen