Wenn sed: 1: "s/foo/bar/g": invalid command code erscheint, ist nichts kaputt. macOS liefert BSD-Werkzeuge aus, Ihr Skript wurde für GNU geschrieben. Gleiche Namen, andere Flags. Das sind die sechs, die wirklich beißen.
1. sed -i verlangt auf macOS ein Argument
$ clai ersetze foo durch bar direkt in config.txt, soll auf mac und linux laufen→ sed -i.bak 's/foo/bar/g' config.txt # portabel: schreibt config.txt.bak
GNU behandelt das Backup-Suffix als optional, BSD verlangt es. sed -i '' 's/…' läuft auf macOS und scheitert auf Linux. sed -i.bak läuft auf beiden – Sie haben nur eine Sicherungsdatei zum Aufräumen.
2. Erweiterte Regex: -E nehmen, niemals -r
$ clai ersetze jede Ziffernfolge durch N mit erweiterter Regex→ echo "foo123" | sed -E 's/[0-9]+/N/'fooN
-r gibt es nur bei GNU. -E versteht beides – GNU akzeptiert es seit Jahren. Machen Sie -E zur Gewohnheit, und eine ganze Fehlerklasse verschwindet.
3. date: -d auf Linux, -r auf macOS
$ clai wandle den Unix-Zeitstempel 1735689600 in ein lesbares Datum in UTC um→ date -u -d @1735689600 '+%Y-%m-%d %H:%M:%S UTC' # GNU2025-01-01 00:00:00 UTC→ date -u -r 1735689600 '+%Y-%m-%d %H:%M:%S UTC' # BSD / macOS
Hier gibt es keine portable Schreibweise. Verzweigen Sie über uname oder installieren Sie GNU coreutils und rufen gdate auf.
4. stat: -c auf Linux, -f auf macOS
$ clai gib Größe und Namen dieser Datei aus→ stat -c '%s %n' t.txt # GNU4 t.txt→ stat -f '%z %N' t.txt # BSD / macOS
Anderes Flag und andere Formatangaben. Wer mit stat etwas Ernsthaftes vorhat, nimmt auf Linux find -printf oder für den portablen Fall wc -c.
5. grep -P existiert auf macOS nicht
$ clai hol nur die Ziffern aus diesem String, portabel→ echo "abc123" | grep -Eo '[0-9]+'123
grep -P (Perl-Regex) ist eine GNU-Build-Option, macOS liefert sie nicht mit. -E deckt die meisten realen Muster ab; wer wirklich Lookahead braucht, braucht perl oder ripgrep, nicht grep.
6. xargs -r gibt es nur bei GNU – und Sie brauchen es
$ clai finde .log-Dateien älter als 30 Tage und lösche sie, ohne rm auf leerer Liste→ find . -name '*.log' -mtime +30 -print0 | xargs -0 -r rm
Ohne -r startet GNU-xargs den Befehl bei leerer Eingabe einmal ganz ohne Argumente – so wird xargs rm im leeren Verzeichnis zum Fehler und xargs docker rm zur Überraschung. BSD-xargs läuft bei leerer Eingabe ohnehin nicht, dort ist -r überflüssig und in alten Versionen unbekannt.
Stolperfallen
brew install coreutilsbringt Zwillinge mitg-Präfix –gsed,gdate,gstat. Wergnubinin den PATH legt, macht den Mac zu Linux: repariert das eigene Notebook und versteckt den Bug vor dem Rest des Teams.- Auf
readlink -fist kein Verlass. Ältere macOS-Versionen kennen es nicht. Nehmen Sierealpath, wo vorhanden, sonstgreadlink -f. base64 -dgegen-D. GNU dekodiert mit-d, macOS will historisch-D.
Verwandte Fragen
Was bedeutet «invalid command code» eigentlich? BSD-sed hat das nächste Wort als Backup-Suffix geschluckt und den Rest Ihres Ausdrucks als unbekannten Befehl gelesen. Ein Opfer des Argument-Parsings, kein Regex-Problem.
Ist macOS BSD oder Linux? Weder noch. Sein Userland stammt von FreeBSD ab – daher gleiche Namen wie unter Linux, aber andere Flags.
Wie schreibe ich ein Skript für beide? POSIX-Flags verwenden, -E bevorzugen, immer sed -i.bak schreiben und auf beiden Systemen testen, bevor es in die CI geht.
Siehe auch
- Derselbe Ablauf unter Windows: PowerShell und cmd gleichauf
- Netzwerkdiagnose in Alltagssprache: Verbindungen, Ports, DNS
- Vom Einzeiler zum eingecheckten Skript: wann der Wechsel lohnt
CliAI erkennt Betriebssystem und Shell und erzeugt die Flags, die diese Maschine tatsächlich akzeptiert. In einer Zeile installieren.