- AI/Regelwerk/windows-shell.md Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
6.1 KiB
type, title, status, summary, tags, created, updated
| type | title | status | summary | tags | created | updated | |||
|---|---|---|---|---|---|---|---|---|---|
| resource | Skripte und Shellbefehle unter Windows | pending-review | Verbindliche Regeln für Befehle und Skripte auf Pascals Windows-Maschine: welche Shell, welches Python, Kodierung, Zeilenenden, Quoting-Schichten, WSL und ssh. |
|
2026-09-13 | 2026-10-29 |
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
bashaufrufen, weder aus Python noch aus PowerShell. Windows sucht einen Programmnamen ohne Pfad zuerst inSystem32. 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 mitwsl -d <Distro>an.shutil.which("bash")taugt nicht als Prüfung. (bash-startet-unter-windows-den-wsl-stub) python, nichtpython3.python3ist hier der Microsoft-Store-Stub.PYTHONIOENCODING=utf-8vor jedem Python-Aufruf, der Umlaute oder Sonderzeichen ausgibt. Die Konsole fährt cp1252, und ohne die Variable bricht ein Skript mitUnicodeEncodeErrorab oder zerlegt die Ausgabe.- ⚠ Mit
python -Iwirkt die Variable nicht:-Ischließt-Eein und ignoriert allePYTHON*-Variablen. Dannpython -I -X utf8. Das trifft auchPYTHONDONTWRITEBYTECODE: Soll kein.pycim Projekt landen, zusätzlich-B. (python-isoliert-ignoriert-pythonioencoding)
- ⚠ Mit
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 Laufpython -m py_compile datei.py. (python-heredoc-bricht-an-anfuehrungszeichen) - Kein
sedfü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
.ps1mit 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-Stringmit 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 einbyte[]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,
$ErrorActionPreferencelokal aufContinuesetzen und imfinallyzurücksetzen. UnterStopwirft2>&1schon 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_ASKPASSohne Leerzeichen im Pfad, und vor der ersten Verbindung einmal probeweise starten. Windows-OpenSSH startet askpass perposix_spawnp; scheitert das an einem Leerzeichen, schickt ssh ein leeres Passwort und erzeugt einen Fehlversuch am Ziel, der eine Login-Sperre füttert.UserKnownHostsFileohne~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/tmpund startest sie dann. (pruefskript-liest-stdin)
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
- CLAUDE
- AI/Regelwerk/codeworkflow: Escaping-Schichten in Plänen
- AI/Regelwerk/navigation: Werkzeuge unter
.vault-tools/