Open Source im professionellen Einsatz

Shellskripte aus der Stümper-Liga – Folge 18: Bash Completion

Bash Bashing

Über Klicki-Bunti und grafische Oberflächen sollten Kommandozeilen-Fans gerechterweise nur dann die Nase rümpfen, wenn sie die Effizienz steigernden Bedienungstricks der interaktiven Shell auch wirklich kennen und benutzen. Diesmal: Bash Completion.

Das Zauberwort, um einerseits die Anzahl der Tastendrücke zu reduzieren und andererseits eventuell folgenreiche Vertipper zu vermeiden, heißt Vervollständigung (Completion). Die [Tab]-Taste schätzt vermutlich jeder Konsolenbenutzer: Sie ergänzt Kommandos am Zeilenanfang sowie Verzeichnis- oder Dateinamen. Die Doppel-[Tab]-Folge kennt mancher nicht, namentlich Linuxer, die solitären Leuchttürmen gleich in einem Meer von Windows-Benutzern stehen. Denen schaut nie ein Gleichgesinnter über die Schulter und sagt: "Spar dir »ls« -»cd« -»ls« …-Orgien, und tippe einfach »cd [Tab][Tab]« , dann zeigt die Shell eine Liste!"

Vervollständigung ist keine Kernfunktionalität der Bash, sondern der Readline-Bibliothek. Die Readline-Funktion »complete()« löst das automatische Erweitern eines Textes aus. Sie ist normalerweise an die [Tab]-Taste gebunden. Viele Programme nutzen die Readline-Bibliothek, weshalb der Completion-Mechanismus auch solchen Tools zur Verfügung steht.

Auf der Kommandozeile entscheidend ist der Text vor dem Cursor. Fängt er mit einem Dollarzeichen an, sucht Readline in der Liste der Variablen, bei einer Tilde unter den in »/etc/passwd« definierten Benutzern und beim Klammeraffen in der Liste der Hosts. Einen Text ohne Sonderzeichen interpretiert die Vervollständigung am Zeilenanfang als Beginn eines Kommandos – inklusive Aliase und Shellfunktionen. Wenn nichts zutrifft, dann versucht die Bash Filename-Completion, das heißt »complete()« ergänzt den Text durch Datei- oder Verzeichnisnamen im aktuellen Verzeichnis.

Im Hintergrund werkeln für alle diese Vervollständigungen eigene Readline-Funktionen (»complete-command« , »complete-filename« , »complete-into-braces« , »complete-username« , »complete-hostname« , »complete-variable« ). Mit

bind -p | grep complete

bekommen Bash-Benutzer zu sehen, an welche Tasten diese Sonderfunktionen auf ihrem System gebunden sind. [Tab] ist nämlich nicht die einzige Taste, die Vervollständigung auslöst. Hostname-Ergänzung erweist sich zum Beispiel als nützlich, wenn man die Hostnamen-Vervollständigung ohne den Klammeraffen benötigt, etwa:

scp Datei Zielr[Esc][Alt Gr]+[Q]

Das ergänzt die Bash dann zu

scp Datei Zielrechner

Die Tastenkombination [Esc][Alt Gr]+[Q], also [Meta][@], ist normalerweise mit »complete-hostname« verknüpft und ergänzt den Anfang des eingegebenen Hostnamens. Diese Kombination liegt – wie auch ein paar andere – für deutsche Tastaturen recht ungünstig. Profis tragen deshalb in ihre »~/.bashrc« die Zeile

bind '"\eh": complete-hostname'

ein und nutzen anschließend das leichter erreichbare [Esc][H], was sogar einen Tastenanschlag spart.

Manual führt aufs Glatteis

Sowohl Hostname-Completion als auch User-Completion halten für den Benutzer ein paar Fallstricke bereit. Beispielsweise liest die Bash die Hostnamen aus der Datei, auf die die Variable »HOSTFILE« zeigt. Laut Bash-Manual bedeutet eine gesetzte, aber leere »HOSTFILE« -Variable, dass die Bash die »/etc/hosts« liest. Wenn die Variable nicht gesetzt ist, so ist die Liste für die Vervollständigung leer.

Doch hier irrt das Bash-Manual, genau das Gegenteil ist der Fall: Die Variable muss entweder ungesetzt oder zumindest mit irgendwas gefüllt sein – die »HOSTFILE« -Datei braucht nicht zu existieren, damit »/etc/hosts« als Quelle dient. In größeren Umgebungen ist »/etc/hosts« sowieso meist leer. Hier kann sich jeder Nutzer ein eigenes »HOSTFILE« mit Favoriten anlegen und die gleichnamige Variable in der »~/.bashrc« setzen.

User-Completion wertet normalerweise die »/etc/passwd« aus. In Netzen, die die Benutzernamen in einem Verzeichnisdienst hinterlegen und NSS-LDAP nutzen, löst die Bash bei User-Completion eine LDAP-Anfrage aus. Das kann quälend lange dauern, die Bash scheint einzufrieren. Und: Je nach Größe der Organisation liefert so eine Anfrage sehr viele Benutzernamen zurück, [~][Tab][Tab] beispielsweise fragt alle Nutzer im LDAP ab! Leider gibt es keine zu »HOSTFILE« äquivanente Umgebungsvariable für die Benutzervervollständigung.

Die eigene Completion

Das Bash-eigene System für die Vervollständigung kann der Benutzer selbst erweitern. Dazu dient unter anderem das Bash-interne Kommando »complete« . Die Funktion ist nicht ganz trivial, was sich schon an der Ausführlichkeit des Manpage-Abschnittes ablesen lässt. Am einfachsten ist Word-Completion: Ein kleines Synchronisationsskript des Autors nimmt als einziges Argument ein Profil entgegen. Das Kommando

complete -W "home data images baw" syncfiles

sorgt dafür, dass die Bash die möglichen Profilnamen für das Kommando »syncfiles« automatisch per [Tab] ergänzt. Mächtiger als »-W« ist die Option »-F« , die als Argument eine Shellfunktion erwartet. Diese berechnet aus der aktuellen Kommandozeile die möglichen Vervollständigungen und legt sie in dem Array »COMPREPLY« ab. Das Listing 1 zeigt ein aufs Nötigste reduziertes Beispiel.

Listing 1

Vervollständigung per Shellfunktion

001 #!/bin/bash
002
003 oocalc_complete() {
004   local ext="ods"
005   local word="$2"
006
007   # Standard-Vervollständigung (filename-completion)
008   local i=0 line
009   declare -a liste
010   while read line; do
011     liste[i++]="$line"
012   done < <(compgen -f -- "$word")
013
014   # Filtern: Nur Dateinamen mit der richtigen Extension
015   local w e
016   for w in "${liste[@]}"; do
017     if [ -d "$w" ]; then
018       continue
019     else
020       e="${w##*.}"
021       if [ "$e" = "$ext" ]; then
022         COMPREPLY[i++]="$w"
023       fi
024     fi
025   done
026 }
027
028 complete -o plusdirs -F oocalc_complete oocalc

Die vorliegende Complete-Spezifikation sorgt dafür, dass Bash für das »oocalc« -Kommando nur Verzeichnisse und ODS-Dateien vervollständigt. Zuerst erzeugt die Shellfunktion in den Zeilen 8 bis 12 eine Liste mit allen Dateien und Verzeichnissen, die eine normale Vervollständigung erfassen würde. Danach filtert das Skript alle Verzeichnisse und unpassenden Dateien heraus. Gültige Vervollständigungen landen in Zeile 22 im Array »COMPREPLY« . Solche Klimmzüge sind leider notwendig, da die »complete« -Standardoptionen »-X« und »-G« leider nur fürs Filtern von Dateinamen gedacht sind und nicht mit der Autovervollständigung von Verzeichnisnamen zusammenspielen.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 2 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook