fish

23. November 2019 (letzte Änderung am 29. Mai 2022)

Die fish (friendly interactive shell) hat mich wegen dieser Funktionen überzeugt:

Die Installation ist einfach und ich musste nicht viel konfigurieren bis ich mir sicher war, dass ich die bash als Standard-Shell ersetzen wollte.

Installation

Arch Linux

sudo pacman -S fish

Ubuntu 20.04

Da in den Standardpaketen vieler Linux-Distributionen oft nicht die aktuellsten Versionen enthalten sind, empfehle ich, in Ubuntu 20.04 das fish-shell-PPA hinzuzufügen:

sudo apt-add-repository ppa:fish-shell/release-3
sudo apt-get update
sudo apt-get install fish

Alternativ kann man auch die .deb-Pakete runterladen und dann installieren mit

dpkg -i fish_3.4.1-1~focal_amd64.deb

Konfiguration

Die Konfiguration kann teilweise über den Browser durchgeführt werden. Das Kommando fish_config öffnet die Konfigurationsseite. Da kann zum Beispiel ein Farbschema und ein vorkonfigurierter Prompt ausgewählt werden (ich benutze Informative Vcs).

Weitergehende Eintstellungen erfolgen in der Datei ~/.config/fish/config.fish (entspricht der ~/.bashrc). Hier ein Beispiel:

# load aliases
if [ -f $HOME/.config/fish/aliases.fish ]
  source $HOME/.config/fish/aliases.fish
end

# don't shorten path in prompt
set -U fish_prompt_pwd_dir_length 0

Aliasse / Abbreviations

bash-Aliasse funktionieren in der Regel auch in der fish. Dafür kann man einfach die .bash_aliases kopieren

cp ~/.bash_aliases ~/.config/fish/aliases.fish

und wie im Beispiel oben einbinden.

Eventuell sind kleine Anpassungen nötig, wenn im Alias Variablen gesetzt werden oder wenn ANSI-C Strings verwendet werden (alias xy=$'\'complicated\' \"command\"'). Außerdem können in fish Aliasse keine anderen Aliasse aufrufen.

Zusätzlich zu Aliassen gibt es in fish noch Abbreviations. Diese sind Aliassen sehr ähnlich. Sie unterscheiden sich dadurch, dass sie während der Eingabe nach einem Leerzeichen oder Return expandiert werden und dass sie verkettet werden können. Beispiel:

abbr rsyncp 'rsync --info=progress2 -ah'

Wichtige Unterschiede zwischen bash und fish als interaktive Shell

bashfishErläuterung
y=5set y 5Variablenzuweisung mit set
export y=5set -x y 5Variablen exportieren mit set -x oder set --export
mkdir "$folder"mkdir $folderVariablen mit Leerzeichen müssen nicht in Anführungszeichen stehen
$(command) oder `command`(command) oder $(command)Kommando-Substitution in einfachen Klammern. fish unterstützt seit Version 3.4.0 auch die POSIX-Schreibweise $(command)
$?$statusExit status des letzten Kommandos

Wenn du ein bash-Kommando in der fish-Shell ausführen möchtest, sind manchmal kleine Anpassungen notwendig (wie in der obenstehenden Tabelle aufgelistet).

Beispiele:

  1. Kann unverändert in die fish eingefügt werden:
    cd ~/workspace && git clone --depth 1 https://github.com/junegunn/fzf.git
  2. In fish-Versionen < 3.4.0 muss hier das $-Zeichen entfernt werden:
    ps wup $(pgrep -f python)
  3. export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

    muss ersetzt werden durch

    set -x JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64
  4. Um einen größeren Code-Block auszuführen, kann auch einfach kurz in die bash gewechselt werden:
    ~ ▶ bash
    ~ $ awk 'BEGIN{
    >     s="/\\/\\/\\/\\/\\"; s=s s s s s s s s;
    >     for (colnum = 0; colnum<77; colnum++) {
    >         r = 255-(colnum*255/76);
    >         g = (colnum*510/76);
    >         b = (colnum*255/76);
    >         if (g>255) g = 510-g;
    >         printf "\033[48;2;%d;%d;%dm", r,g,b;
    >         printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
    >         printf "%s\033[0m", substr(s,colnum+1,1);
    >     }
    >     printf "\n";
    > }'
    [Ausgabe]
    Zurück zur fish mit Strg-D
    ~ ▶
    

Funktionen/Shortcuts

Funktion bash fish
vorheriges Wort löschen Ctrl+w
nächstes Wort löschen Alt+d
letztes Argument des letzten Kommandos einfügen Alt+.
Undo Ctrl+_ Ctrl+_ / Ctrl+z
Alias expandieren Ctrl+Alt+e
Bis Wortende in Großbuchstaben umwandeln Alt+u
Bis Wortende in Kleinbuchstaben umwandeln Alt+l
Nächstes Zeichen explizit einfügen Ctrl+v
Zeile auskommentieren und neue beginnen Alt+#
Leerzeichen um den Cursor löschen Alt+\
Aktuelle Zeile in $EDITOR bearbeiten Ctrl+x Ctrl+e Alt+e
Während Eingabe Inhalt des aktuellen Ordners anzeigen
Alt+l
sudo vorne einfügen
Alt+s
&| less; hinten anhängen (p wie Pager)
Alt+p

bash vs fish als Skriptsprache

Wer fish als interaktive Shell benutzt, muss nicht zwangsläufig auch fish-Skripte schreiben. Ich schreibe ganz triviale Skripte nach Möglichkeit POSIX-konform, damit sie mit der extrem schnellen Dash ausgeführt werden können. Für große Projekte benutze ich Python. Für alles dazwischen benutze ich lieber fish als bash, weil in fish vieles logischer oder benutzerfreundlicher ist als in bash.

Hier ein paar Beispiele, wie man Dinge in bash und in fish schreibt:

bashfishErläuterung
echo ${var,,}string lower $varVariable in Kleinbuchstaben umwandeln
var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}"
echo $var
string trim $varVariable ohne Leerzeichen
am Anfang und am Ende ausgeben
if [[ ":$PATH:" == *":/bin:"* ]]; thenif contains /bin $PATHTesten, ob /bin in $PATH enthalten ist
echo ${#arr[@]}count $arrDie Länge eines Arrays ausgeben
echo $(tput setaf 4)blue$(tput sgr0)xxecho (set_color blue)blue(set_color normal)xxEin farbiges Wort ausgeben

Alternativen / Warum nicht zsh?

Wie vermutlich die meisten Linux-Nutzer habe ich jahrelang die bash benutzt, einfach nur weil sie in den meisten Distributionen die Standard-Shell ist.

Vor einem Jahr hab ich mal die zsh (+ohmyzsh) ausprobiert, weil mir die Tab-Funktionalität und die Git-Information im Prompt dort gefallen haben. Aber dafür haben mich ein paar andere Dinge gestört: Zum Beispiel kann man in der bash mit Alt+Backspace das letzte Wort und mit Ctrl+w alles bis zum letzten Leerzeichen (also etwa einen kompletten Dateipfad) löschen. In der zsh machen beiden Tastenkombinationen das Gleiche. Wie unsinnig! Und eine Tab-Vervollständigung mit Tab und Auswahl mit den Pfeiltasten sieht auch nur auf den ersten Blick praktisch aus (weil das Rübergreifen zu den Pfeiltasten auch nicht schneller geht, als die Suche durch ein paar zusätzliche Buchstaben weiter einzugrenzen). Ich hab dann letztendlich lieber das Tab-Verhalten und den Prompt in der bash angepasst und war damit zufrieden. Wer sowieso schon die zsh benutzt, kann sich aber auch die besten Funktionen der fish (automatische Vorschläge und Syntax-Highlighting) per Plugin nachladen.

Weil ich sehr gerne in Python programmiere, finde ich auch die xonsh (Pythonish, BASHwards looking shell) sehr interessant. Ich weiß nur noch nicht, ob ich die leicht erhöhten Ladezeiten für ein neues Fenster/einen neuen Tab in Kauf nehmen möchte, wo ich die Vorteile der xonsh vermutlich kaum nutzen würde.