Ausgangslage: Interaktive Shell ist Fish. Die folgenden sechs Versionen des selben Skripts werden ausgeführt, um die Unterschiede herauszuarbeiten.
#!/bin/fish
please nala update;
please nala upgrade -y;
please nala full-upgrade -y;
please nala autoremove -y;
please nala autopurge -y;
echo '';
ffplay -nodisp -autoexit -loglevel quiet ~/skripte/baf/Burp.mp3
echo '$> done.';
echo '';
# funktioniert
#!/bin/bash
please nala update;
please nala upgrade -y;
please nala full-upgrade -y;
please nala autoremove -y;
please nala autopurge -y;
echo '';
ffplay -nodisp -autoexit -loglevel quiet ~/skripte/baf/Burp.mp3
echo '$> done.';
echo '';
# bash kennt please nicht
#!/bin/fish
sudo nala update;
sudo nala upgrade -y;
sudo nala full-upgrade -y;
sudo nala autoremove -y;
sudo nala autopurge -y;
echo '';
ffplay -nodisp -autoexit -loglevel quiet ~/skripte/baf/Burp.mp3
echo '$> done.';
echo '';
# funktioniert
#!/bin/bash
sudo nala update;
sudo nala upgrade -y;
sudo nala full-upgrade -y;
sudo nala autoremove -y;
sudo nala autopurge -y;
echo '';
ffplay -nodisp -autoexit -loglevel quiet ~/skripte/baf/Burp.mp3
echo '$> done.';
echo '';
# bislang beste Version
#!/bin/fish
nala update;
nala upgrade -y;
nala full-upgrade -y;
nala autoremove -y;
nala autopurge -y;
echo '';
ffplay -nodisp -autoexit -loglevel quiet ~/skripte/baf/Burp.mp3
echo '$> done.';
echo '';
# es fehlt an root-Rechten
# sollte das Skript mit root-Rechten ausgeführt werden, kann ffplay nicht ausgeführt werden, weil das im Userkontext laufen muss.
#!/bin/bash
nala update;
nala upgrade -y;
nala full-upgrade -y;
nala autoremove -y;
nala autopurge -y;
echo '';
ffplay -nodisp -autoexit -loglevel quiet ~/skripte/baf/Burp.mp3
echo '$> done.';
echo '';
# es fehlt an root-Rechten
# sollte das Skript mit root-Rechten ausgeführt werden, kann ffplay nicht ausgeführt werden, weil das im Userkontext laufen muss.
Die Kernprobleme in diesem Fall sind:
- Aliase gelten nicht in nicht-interaktiven Shells (also in Skripten).
pleaseist ein Alias, kein eigenständiges Programm.- bash und fish behandeln Aliase und Funktionen völlig unterschiedlich – sie teilen sich keine Alias-Definitionen.
Das heißt:
- Bei
#!/bin/fishfunktioniertplease, weil fish das Alias kennt (please.fish). - Bei
#!/bin/bashkannpleasenicht funktionieren, denn bash kennt das Alias nicht, weil es in der.bashrcnicht existiert (und selbst wenn, wird die bei Skriptaufruf sowieso nicht geladen!). - Wenn das ganze Skript mit
please ./skript.shgestartet wird, läuft alles als root, auch der ffmpeg-Aufruf – undffmpegkann dann u. U. keine Audiosession starten (weil der root-User z.B. keinen Zugriff auf den PulseAudio- oder PipeWire-Sessionbus des Users hat).
Fazit:
- Der Gedanke, bash als Skriptbasis zu behalten und fish als interaktive Shell zu nutzen, ist eindeutig die sauberste Lösung:
- Systemweite Kompatibilität bleibt gewahrt.
- Alias-Abhängigkeiten werden vermieden.
- Klare Trennung zwischen „interaktivem Komfort“ (fish) und „systemweiter Kompatibilität“ (bash).
Das bedeutet konkret:#!/bin/bash in allen Skripten behalten.please überall entfernen und, wenn nötig, direkt sudo verwenden.
Und wenn man „please“ einfach generell verfügbar machen würde?
Wenn du unbedingt das please-Feeling in bash willst, dann leg dir ein winziges Wrapper-Skript an:
#!/bin/bash
exec sudo "$@"
und speichere das als /usr/local/bin/please.
Dann noch mit chmod a+x ausführbar machen.
Damit ist please ein echtes Programm und funktioniert dann auch in bash-Skripten, Cronjobs usw.
Ja aber
beißt sich das nicht mit meiner Funktion „please.fish„, weil etwas in /usr/local/bin ja auch systemweit und unabhängig von der Shell einsetzbar wäre?
Nein, das Stichwort heißt Kommandoauflösungsverfahren (englisch: command resolution oder command lookup order).
🧩 Allgemeines Prinzip (vereinfachte Darstellung)
- Shell-eigene Schlüsselwörter / Syntaxelemente
→ z. B.if,for,while,function,[[ ... ]]
Diese sind Teil der Sprache selbst, keine Kommandos. - Aliase (bash, zsh) oder Abbreviations (fish)
→ werden rein textuell ersetzt, bevor der Befehl überhaupt interpretiert wird. - Shell-Funktionen
→ benutzerdefinierte Funktionen, die in der aktuellen Session bekannt sind.
Diese haben Vorrang vor externen Programmen gleichen Namens. - Shell-Builtins
→ interne Befehle, die direkt im Shell-Prozess implementiert sind
(z. B.cd,echo,test,export,read). - Externe Programme
→ in$PATHgesucht, beginnend beim ersten Eintrag (meist/usr/local/bin,/usr/bin, …).
Der erste Treffer gewinnt. - (Optional) Funktionen oder Hooks aus Plugins / Completion-Systemen
→ z. B. in fish oder zsh kann es zusätzliche Lookup-Schichten geben.
Reihenfolge bei Bash
Bash beschreibt das, laut man bash, Abschnitt COMMAND EXECUTION, so:
- Alias expansion
- Function lookup
- Builtin lookup
- $PATH search
Reihenfolge bei Fish
Fish macht es etwas moderner und konsistenter:
- Abbreviations (Abkürzungen) – werden beim Tippen expandiert, nicht zur Laufzeit.
- Functions – alle Funktionen in
~/.config/fish/functions/oder geladenen Plugins. - Builtins – interne Kommandos (
set,cd,status, …). - Externe Kommandos – gesucht in
$PATH(Reihenfolge der PATH-Einträge). - Implicit cd – falls kein Kommando gefunden wird, aber ein Ordner gleichen Namens existiert, führt fish
cddorthin aus (nur in interaktiven Sessions).