Die Bash Eingabeaufforderung anpassen

Anzeige zusätzlicher Informationen in der Eingabeaufforderung der Bash

Die Eingabeaufforderung der Bash ist nicht fest definiert sondern lässt sich vom Systemverwalter für alle Benutzer und vom einzelnen Benutzer für sich selbst anpassen. Dieser Artikel zeigt, wie man zusätzliche Informationen in die Eingabeaufforderung der Bash bringt.

Definition der Eingabeaufforderung

Inhalt und Aussehen der Eingabeaufforderung der Bash werden mittels der Umgebungsvariablen PS1 definiert. Wie die aktuelle Eingabeaufforderung definiert ist, erfährt man, wenn man den Inhalt der Variablen ausgibt:

uwe@Caboto:~$ echo $PS1
${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
uwe@Caboto:~$

Was zunächst wie unverständlicher Programmcode aussieht, lässt sich relativ einfach aufschlüsseln:

${debian_chroot:+($debian_chroot)} – Diese Sequenz sorgt für einen zusätzlichen Inhalt, falls die Shell sich gegenwärtig in einer chroot Umgebung befindet. Das ist normalerweise nicht der Fall und dann wird auch nichts ausgegeben.

\[\033[01;32m\] – Mit \[…\] wird generell eine Sequenz nicht-druckbarer Zeichen eingebettet, in diesem Fall \033[01;32m, was eine Änderung der Farbe der nachfolgenden (wieder druckbaren) Zeichen zu grün ("light green") bewirkt. Diese sind

\u@\h\u und \h sind zwei von mehreren möglichen Makros, die in der Eingabeaufforderung verwendet werden können, \u enthält den aktuellen Benutzernamen und \h den aktuellen Rechnernamen. Hier wird noch ein @ Zeichen zwischen beide platziert.

Anschließend erfolgt mit \[\033[00m\] eine Rücksetzung der zuvor geänderten Attribute, sodass der Text wieder normal in weiß erscheint, sodann ein Doppelpunkt : und anschließend wieder mit \[\033[01;34m\] eine Änderung der Farbe in blau ("light blue"), in welcher dann mit dem Makro \w das gegenwärtige Arbeitsverzeichnis ausgegeben wird. Danach erfolgt mit \[\033[00m\] wieder eine Rücksetzung der Attribute.

Zum Schluss wird mit dem Makro \$ tatsächlich nur ein $ Zeichen angezeigt, falls es sich beim aktuellen Benutzer nicht um den Systemverwalter root handelt, wohingegen bei root mit diesem Makro ein # Zeichen angezeigt wird.

Ziel ist es nun, die EIngabeaufforderung so anzupassen, dass beim Wechsel in ein Verzeichnis, das der Versionsverwaltung mit Git unterliegt, der gegenwärtige Branch und das aktuelle Tag (sofern vorhanden) in der Eingabeaufforderung angezeigt werden.

Ein Git-Repository in der Bash anzeigen

Das Verzeichnis /home/uwe/ProjectDir/MyProject/ ist das Basisverzeichnis eines Projektes, das mit Git verwaltet wird. In der Bash könnte es ungefähr so aussehen:

Mit dem Befehl git branch oder git rev-parse -abbrev-ref HEAD kann man herausfinden, auf welchem Branch in einem Git-Repository man sich befindet:

$ git rev-parse --abrev-ref HEAD
master
$

Befindet man sich nicht in einem Verzeichnis eines Git-Repositories, erfolgt eine Fehlermeldung:

$ git rev-parse --abrev-ref HEAD
fatal: Kein Git-Repository (oder irgendeines der Elternverzeichnisse): .git
$

Um herauszufinden, ob man es ein Tag gibt, kann man den Befehl git describe verwenden. Dieser gibt die gleiche Fehlermeldung wie oben aus, wenn man sich nicht in einem Git-Repository befindet und eine andere, wenn es im Repository kein Tag gibt:

$ git describe
fatal: Keine Namen gefunden, kann nichts beschreiben.
$

Wenn es ein Tag gibt, wird dieses angezeigt:

$ git describe
v3.2.12
$

Um diese Informationen mit Hilfe eines einzigen Befehls verfügbar zu machen, müssen wir zunächst eine Bash-Funktion definieren, die genau diese Inhalte ausgibt.

Eine Funktion current_git_branch definieren

Der geeignete Ort für Funktionsdefinitionen ist die benutzerspezifische Konfigurationsdatei der Bash, .bashrc, die beim Starten einer Bash aufgerufen und ausgeführt wird. Sie ist grundsätzlich im Stammverzeichnis des Benutzers vorhanden und enthält bereits einige Einstellungen.

Eine weitere, bessere Möglichkeit wäre es, Funktionsdefinitionen in einer zusätzlichen Datei, zum Beispiel .bash_functions unterzubringen und diese Datei dann in der .bashrc einzubinden. Das Einbinden der .bash_functions sollte wie folgt aussehen und relativ am Anfang der .bashrc erfolgen, da man ja möglicherweise noch an späterer Stelle innerhalb der .bashrc auf die definierten Funktionen zugreifen will:

if [ -f ~/.bash_functions ]; then
    . ~/.bash_functions
fi

Das bedeutet: Wenn es die Datei .bash_functions im Stammverzeichnis des Benutzers (~) gibt, wird sie eingebunden ("sourced") und die darin enthaltenen Funktionsdefinitionen ausgeführt, ansonsten passiert gar nichts.

Die Definition der Funktion current_git_branch – die auch völlig anders heißen kann – sieht wie folgt aus:

function current_git_branch {
  local version=$(git describe 2>/dev/null);
  local branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null);
  if [[ -n $branch ]];then
    echo " [$branch/$version]";
  fi
}

Die Ausgabe des Befehls git describe wird mittels $(…) erfasst und in der (nur in dieser Funktion gültigen) Variablen version gespeichert. Wichtig ist , dass mit 2>/dev/null eventuelle Fehlerausgaben ins Nichts geschickt werden, sodass bei der späteren Ausgabe der Variablen im Fehlerfall nichts ausgegeben wird.

In gleicher Weise wird die Ausgabe von git rev-parse -abbrev-ref HEAD in der Variablen branch gespeichert.

Sollte danach die Variable branch nicht leer sein, wird der Inhalt von branch und version mit / getrennt in eckigen Klammern und mit einem Leerzeichen davor ausgegeben.

Mit einer neuen Bash oder mittels "sourcen" der .bashrc (oder der .bash_functions) lässt sich die Funktion testen. Einfach den Befehl current_git_branch ausführen. Wenn das gegenwärtige Verzeichnis nicht unter Versionskontrolle steht, wird nichts erscheinen, anderfalls müsste z.B. [master/] oder [master/1.2.3] ausgegeben werden, je nachdem in welchem Branch man sich gerade befindet und ob es ein Tag gibt.

Die Funktion der Eingabeaufforderung hinzufügen

Die Ausgabe des Befehls current_git_branch wird nun mittels $(current_git_branch) der Eingabeaufforderung an einer geeigneten Stelle hinzugefügt, am besten nach dem gegenwärtigen Verzeichnis und vor dem $ Zeichen. Dazu muss die Definition der Variablen PS1 in der .bashrc geändert werden:

Die Definition von PS1 endet üblicherweise wie oben beschrieben:

PS1='...\w\[\033[00m\]\$ '

Das wird geändert zu:

PS1='...\w$(current_git_branch)\[\033[00m\]\$ '

Sobald man eine neue Bash gestartet oder die .bashrc erneut eingebunden hat ist die neue Eingabeaufforderung wirksam:

Weiterführende Literatur

Bash Prompt HOWTO: Chapter 6. ANSI Escape Sequences: Colours and Cursor Movement

Top