Nehmen wir einmal an, Sie hätten gerade einen längeren Befehl mit einer umfangreichen Pipeline ausgeführt, wie diesen hier aus »Dateiduplikate entdecken« auf Seite 33:
$ md5sum *.jpg | cut -c1-32 | sort | uniq -c | sort -nr
und wollten ihn ein zweites Mal aufrufen. Tippen Sie ihn auf keinen Fall noch einmal ein! Bitten Sie stattdessen die Shell, in der History zurückzugehen und den Befehl erneut auszuführen. Hinter den Kulissen zeichnet die Shell die Befehle auf, die Sie aufrufen, sodass Sie ganz leicht zurückgehen und sie mit nur wenigen Tastendrücken noch einmal ausführen können. Diese Shell-Eigenschaft wird als Befehls-History bezeichnet. Geübte Linux-Anwender nutzen die Befehls-History oft und regelmäßig, um ihre Arbeit zu beschleunigen und keine Zeit zu verschwenden.
Stellen Sie sich außerdem vor, Sie hätten sich beim Eintippen des gerade gezeigten Befehls vertippt, also etwa »jpg« als »jg« eingegeben:
$ md5sum *.jg | cut -c1-32 | sort | uniq -c | sort -nr
Um den Fehler zu beheben, drücken Sie nun nicht unzählige Male auf die Backspace-Taste und tippen alles neu ein. Stattdessen ändern Sie den Befehl an der entsprechenden Stelle. Die Shell unterstützt das Kommandozeilen-Editing zum Korrigieren von Tippfehlern und Durchführen aller möglichen Veränderungen, wie man sie auch in einem Texteditor durchführen könnte.
Dieses Kapitel zeigt Ihnen, wie Sie mit der Befehls-History und dem Kommandozeilen-Editing viel Zeit sparen. Wie immer werde ich mich nicht um Vollständigkeit bemühen, sondern mich auf die praktischsten und sinnvollsten Teile dieser Shell-Eigenschaft konzentrieren. (Falls Sie eine andere Shell als die bash nutzen, finden Sie in Anhang B zusätzliche Hinweise.)
All die Ratschläge in diesem Buch nützen Ihnen mehr, wenn Sie schnell tippen können. Ganz egal, wie viel Sie wissen, wenn Sie 40 Wörter pro Minute tippen und Ihre ebenso sachkundige Freundin 120, dann arbeitet sie dreimal schneller als Sie. Recherchieren Sie im Web nach »Tippgeschwindigkeit testen«, um Ihre Geschwindigkeit zu messen, und suchen Sie sich dann einen Kurs oder ein Tutorial, mit dem Sie Ihre Fähigkeiten verbessern können. Versuchen Sie, auf 80 bis 100 Wörter pro Minute zu kommen. Der Aufwand lohnt sich. |
Eine Befehls-History ist einfach eine Liste von früheren Befehlen, die Sie in einer interaktiven Shell ausgeführt haben. Um die History einer Shell anzuschauen, führen Sie den Befehl history aus, der in die Shell eingebaut ist, ein sogenanntes Builtin. Die Befehle erscheinen in chronologischer Reihenfolge mit ID-Nummern für eine einfache Referenz. Die Ausgabe sieht ungefähr so aus:
$ history
1000 cd $HOME/Music
1001 ls
1002 mv jazz.mp3 jazzy-song.mp3
1003 play jazzy-song.mp3
... 479 Zeilen weggelassen.
1481 cd
1482 firefox https://google.com
1483 history Enthält auch den gerade ausgeführten Befehl.
Die Ausgabe von history kann Hunderte von Zeilen (oder mehr) lang sein. Beschränken Sie sie auf die letzten Befehle, indem Sie ein Integer-Argument angeben, das die Anzahl der auszugebenden Zeilen bestimmt:
$ history 3 Gibt die 3 letzten Befehle aus.
1482 firefox https://google.com
1483 history
1484 history 3
Da history auf die Standardausgabe schreibt, können Sie die Ausgabe auch mit Pipes verarbeiten. Betrachten Sie zum Beispiel Ihre History bildschirmweise:
$ history | less älteste bis jüngste Einträge
$ history | sort -nr | less jüngste bis älteste Einträge
oder geben Sie nur die Befehle aus der History aus, die cd enthalten:
$ history | grep -w cd
1000 cd $HOME/Music
1092 cd ..
1123 cd Finances
1375 cd Checking
1481 cd
1485 history | grep -w cd
Um die History der aktuellen Shell zu bereinigen (zu löschen), verwenden Sie die Option -c:
$ history -c
Ich zeige Ihnen drei zeitsparende Möglichkeiten, Befehle aus der History einer Shell wieder zurückzuholen:
Cursor-Methode
Ausgesprochen einfach zu erlernen, aber in der Praxis oft langsam.
History-Erweiterung
Schwieriger zu erlernen (ziemlich kryptisch, ehrlich gesagt), kann aber sehr schnell sein.
Inkrementelle Suche
Sowohl einfach als auch schnell.
Jede Methode eignet sich für bestimmte Situationen am besten, weshalb ich empfehle, sie alle drei zu erlernen. Je mehr Techniken Sie kennen, umso besser können Sie in jeder Situation die richtige wählen.
Um in einer Shell den vorherigen Befehl zurückzuholen, drücken Sie die Pfeil-nach-oben-Taste. So einfach ist das. Wenn Sie diese Taste immer wieder drücken, gelangen Sie in umgekehrt chronologischer Reihenfolge zu Ihren früheren Befehlen. Drücken Sie Pfeil-nach-unten, um wieder in die andere Richtung zu gehen (also zu den neueren Befehlen). Wenn Sie den gewünschten Befehl erreicht haben, drücken Sie Enter. Der Befehl wird ausgeführt.
Mit den Cursor-Tasten durch die Befehls-History zu wandern, gehört zu den zwei gebräuchlichsten Methoden zum Beschleunigen der Arbeit, die Linux-Benutzer lernen. (Die andere ist das Pattern Matching von Dateinamen mit *, das Sie in Kapitel 2 gesehen haben.) Die Cursor-Methode ist effizient, wenn der gewünschte Befehl noch relativ weit oben in der History liegt – nicht mehr als zwei oder drei Befehle in der Vergangenheit. Liegen Befehle weiter weg, nervt es schnell. Die Pfeiltaste 137-mal zu drücken, bringt es einfach nicht.
Der beste Anwendungsfall für die Cursor-Methode ist das Zurückholen und Ausführen des unmittelbar vorhergehenden Befehls. Bei vielen Tastaturen befindet sich die Pfeil-nach-oben-Taste in der Nähe der Enter-Taste, sodass Sie die beiden Tasten schnell mit wenigen sparsamen Fingerbewegungen betätigen können. Bei einer ausgewachsenen QWERTZ-Tastatur setze ich meinen rechten Ringfinger auf die Pfeiltaste und den rechten Zeigefinger auf Enter. So kann ich beide Tasten effizient betätigen. (Versuchen Sie es.)
Häufig gestellte Fragen über die Befehls-History
Wie viele Befehle sind in der History einer Shell gespeichert?
Das Maximum ist 500 oder die Zahl, die in der Shell-Variablen HISTSIZE angegeben ist, die Sie ändern können:
$ echo $HISTSIZE
500
$ HISTSIZE=10000
Computerspeicher ist so billig und so reichlich vorhanden, dass es sinnvoll ist, HISTSIZE auf einen großen Wert zu setzen, damit Sie auch Befehle aus ferner Vergangenheit wieder zurückholen und erneut ausführen können. (Eine History von 10.000 Befehlen belegt nur etwa 200K an Speicher.) Oder seien Sie ganz übermütig und speichern Sie unbegrenzt viele Befehle, indem Sie den Wert auf -1 setzen.
Welcher Text wird an die History angefügt?
Die Shell fügt genau das in die History ein, was Sie tippen, ohne dass es ausgewertet wird. Wenn Sie ls $HOME ausführen, enthält die History »ls $HOME«, nicht »ls /home/smith«. (Es gibt eine Ausnahme, siehe »History-Ausdrücke tauchen nicht in der Befehls-History auf« auf Seite 59.)
Werden wiederholte Befehle an die History angefügt?
Die Antwort hängt vom Wert der Variablen HISTCONTROL ab. Wenn diese Variable nicht gesetzt ist, wird standardmäßig jeder Befehl angefügt. Ist der Wert ignoredups (was ich empfehle), werden wiederholte Befehle nicht angefügt, solange sie direkt hintereinanderstehen (siehe man bash für andere Werte):
$ HISTCONTROL=ignoredups
Besitzt jede Shell ihre eigene History, oder teilen sich alle Shells eine einzige History?
Jede interaktive Shell besitzt eine separate History.
Ich habe eine neue interaktive Shell gestartet, und sie hat bereits eine History. Wieso das denn?
Immer wenn eine interaktive Shell beendet wird, schreibt sie ihre History in die Datei $HOME/.bash_history bzw. in den Pfad, der in der Shell-Variablen HISTFILE gespeichert ist:
$ echo $HISTFILE
/home/smith/.bash_history
Neue interaktive Shells laden diese Datei beim Start, sodass sie sofort eine History haben. Das ist ein etwas schrulliges System, falls Sie viele Shells betreiben, weil sie alle beim Beenden $HISTFILE schreiben. Es ist also nicht ganz vorhersehbar, welche History eine neue Shell laden wird.
Die Variable HISTFILESIZE kontrolliert, wie viele Zeilen an History in die Datei geschrieben werden. Wenn Sie HISTSIZE ändern, um die Größe der History im Speicher zu beeinflussen, sollten Sie am besten auch gleich HISTFILESIZE aktualisieren:
History-Erweiterung ist eine Shell-Eigenschaft, bei der über besondere Ausdrücke auf die Befehls-History zugegriffen wird. Die Ausdrücke beginnen mit einem Ausrufezeichen, das gern auch als »Bang« bezeichnet wird. So werden zum Beispiel zwei Ausrufezeichen hintereinander (»Bang Bang«) zum unmittelbar vorhergehenden Befehl ausgewertet:
$ echo Efficient Linux
Efficient Linux
$ !! "Bang Bang" = vorhergehender Befehl
echo Efficient Linux Die Shell gibt dankenswerterweise den Befehl aus, der ausgeführt wird.
Efficient Linux
Möchten Sie auf den letzten Befehl zugreifen, der mit einem bestimmten String begann, setzen Sie ein Ausrufezeichen vor diesen String. Um etwa den letzten grep-Befehl noch einmal auszuführen, rufen Sie »Bang grep« auf:
$ !grep
grep Perl animals.txt
alpaca Intermediate Perl 2012 Schwartz, Randal
Wenn Sie auf den letzten Befehl noch einmal zugreifen wollen, der irgendwo einen bestimmten String enthielt, nicht nur am Anfang des Befehls, dann umgeben Sie den String auch noch mit Fragezeichen:1
$ !?grep?
history | grep -w cd
1000 cd $HOME/Music
1092 cd ..
...
Sie können einen bestimmten Befehl aus der History einer Shell auch anhand seiner absoluten Position abfragen – der ID links neben ihm in der Ausgabe von history. So bedeutet zum Beispiel der Ausdruck !1203 (Bang 1023) »Befehl an Position 1023 in der History«:
$ history | grep hosts
1203 cat /etc/hosts
$ !1203 der Befehl an Position 1023
cat /etc/hosts
127.0.0.1 localhost
::1 example.oreilly.com
Ein negativer Wert ruft einen Befehl anhand seiner relativen Position in der History ab anstelle seiner absoluten Position. Zum Beispiel bedeutet !-3 (Bang minus drei) »der Befehl, den Sie vor drei Befehlen ausgeführt haben«:
$ history
4197 cd /tmp/junk
4198 rm *
4199 head -n2 /etc/hosts
4199 cd
4200 history
$ !-3 der Befehl, den Sie vor drei Befehlen ausgeführt haben
head -n2 /etc/hosts
127.0.0.1 localhost
127.0.1.1 example.oreilly.com
Die History-Erweiterung ist schnell und bequem, wenn auch ein bisschen kryptisch. Sie kann jedoch riskant sein, wenn Sie einen falschen Wert angeben und den Befehl blind ausführen. Schauen Sie sich das vorstehende Beispiel genau an. Hätten Sie sich verzählt und !-4 statt !-3 eingetippt, hätten Sie rm * anstelle des gewünschten Befehls head ausgeführt und aus Versehen die Dateien in Ihrem Home-Verzeichnis gelöscht! Um dieses Risiko zu begrenzen, setzen Sie den Modifikator :p hinzu, um den Befehl aus der History nur auszugeben, nicht jedoch auszuführen:
$ !-3:p
head -n2 /etc/hosts Ausgegeben, nicht ausgeführt.
Die Shell setzt den nicht ausgeführten Befehl (head) dann auch in die History, sodass Sie ihn bequem mit einem »Bang Bang« ausführen können, wenn er gut aussieht:
$ !-3:p
head -n2 /etc/hosts Ausgegeben, nicht ausgeführt, und an die History angehängt.
$ !! Der Befehl wird nun tatsächlich ausgeführt.
head -n2 /etc/hosts Ausgegeben und ausgeführt.
127.0.0.1 localhost
127.0.1.1 example.oreilly.com
Manche Menschen bezeichnen die History-Erweiterung als »Bang-Befehle«, dabei sind Ausdrücke wie !! und !grep keine Befehle. Es handelt sich um String-Ausdrücke, die Sie irgendwo in einen Befehl setzen können. Zur Demonstration verwenden Sie echo, um den Wert von !! auf der Standardausgabe auszugeben, ohne ihn auszuführen, und zählen die Anzahl der Wörter mit wc:
$ ls -l /etc | head -n3 Führt irgendeinen Befehl aus.
total 1584
drwxr-xr-x 2 root root 4096 Jun 16 06:14 ImageMagick-6/
drwxr-xr-x 7 root root 4096 Mar 19 2020 NetworkManager/
$ echo "!!" | wc -w Zählt die Wörter in dem vorherigen Befehl.
echo "ls -l /etc | head -n3" | wc -w
6
Dieses Beispiel demonstriert, dass History-Erweiterungen mehr Nutzen bieten als nur das Ausführen von Befehlen. Sie werden im nächsten Abschnitt eine praktischere, leistungsfähigere Technik kennenlernen.
Ich habe hier nur ein paar Eigenschaften der Befehls-History behandelt. Wenn Sie es ganz genau wissen wollen, führen Sie man history aus.
History-Ausdrücke tauchen nicht in der Befehls-History auf Die Shell hängt den Befehl wortwörtlich an die History an, also ohne ihn auszuwerten, wie ich in »Häufig gestellte Fragen über die Befehls-History« auf Seite 56 bereits erwähnte. Die eine Ausnahme für diese Regel ist die History-Erweiterung. Deren Ausdrücke werden immer ausgewertet, bevor sie zur Befehls-History hinzugefügt werden: |
|
|
$ ls Führt irgendeinen Befehl aus. hello.txt $ cd Music Führt einen anderen Befehl aus. $ !-2 Benutzt History-Erweiterung. ls song.mp3 $ history Betrachtet die History. 1000 ls 1001 cd Music 1002 ls "ls" taucht in der History auf, nicht "!-2". 1003 history |
|
Diese Ausnahme ist auch sinnvoll. Stellen Sie sich vor, Sie versuchten eine Befehls-History zu verstehen, die voller Ausdrücke wie !-15 und !-92 ist, die sich auf andere History-Einträge beziehen. Sie müssten einem Pfad durch die ganze History folgen, um einen einzigen Befehl zu verstehen. |
Haben Sie schon einmal versucht, Dateien mithilfe eines Musters, wie etwa *.txt, zu löschen, dann aber versehentlich das Muster fehlerhaft eingegeben und die falschen Dateien weggeputzt? Hier ist ein Beispiel mit einem versehentlichen Leerzeichen nach dem Asterisk:
$ ls
123 a.txt b.txt c.txt dont-delete-me important-file passwords
$ rm * .txt ACHTUNG, GEFAHR!! Nicht ausführen! Das löscht die falschen Dateien!
Die gebräuchlichste Lösung, um diese Gefahr zu umgehen, besteht darin, einen Alias für rm einzurichten und rm -i auszuführen, sodass vor jedem Löschen eine Bestätigung abgefragt wird:
$ alias rm='rm -i' oft in einer Shell-Konfigurationsdatei zu finden
$ rm *.txt
/bin/rm: remove regular file 'a.txt'? y
/bin/rm: remove regular file 'b.txt'? y
/bin/rm: remove regular file 'c.txt'? y
Nun muss ein zusätzliches Leerzeichen nicht »tödlich« sein, da die Abfrage von rm -i Sie warnt, dass Sie die falschen Dateien zu entfernen im Begriff sind:
$ rm * .txt
/bin/rm: remove regular file '123'? Etwas stimmt nicht: Brechen Sie den Befehl ab!
Die Alias-Lösung nervt allerdings auch, da Sie es meist nicht wollen oder brauchen, dass rm noch einmal nachfragt. Sie funktioniert auch nicht, wenn Sie sich auf einer anderen Linux-Maschine anmelden, auf der es Ihre Aliase nicht gibt. Ich zeige Ihnen einen besseren Weg, das Erfassen der falschen Dateinamen mit einem Muster zu vermeiden. Die Technik besteht aus zwei Schritten und setzt auf die History-Erweiterung:
$ ls *.txt
a.txt b.txt c.txt
$ rm !$
rm *.txt
Die History-Erweiterung !$ (Bang Dollar) bedeutet »das letzte Wort, das Sie in dem vorhergehenden Befehl eingetippt haben«. Deshalb ist rm !$ hier eine Kurzform von »lösche, was immer ich gerade mit ls aufgelistet habe«, nämlich *.txt. Falls Sie versehentlich ein Leerzeichen nach dem Asterisk hinzufügen, zeigt die Ausgabe von ls ganz offensichtlich – und sicher –, dass etwas nicht stimmt:
$ ls * .txt
/bin/ls: cannot access '.txt': No such file or directory
123 a.txt b.txt c.txt dont-delete-me important-file passwords
Gut, dass Sie zuerst ls statt rm ausgeführt haben! Sie können den Befehl nun so modifizieren, dass das Extra-Leerzeichen entfernt wird. Dann geht es sicher weiter. Diese Sequenz aus zwei Befehlen – ls gefolgt von rm !$ – ist eine großartige und sichere Methode für Ihren Linux-Werkzeugkasten.
Bei einer verwandten Technik werfen Sie mit head zuerst einen Blick auf den Inhalt der Datei, um sicherzustellen, dass Sie die richtige Datei beim Wickel haben, bevor Sie rm !$ aufrufen:
Die Shell bietet außerdem eine History-Erweiterung !* (Bang Stern), die alle Argumente erfasst, die Sie im vorherigen Befehl eingetippt haben, statt nur das letzte Argument mitzunehmen:
$ ls *.txt *.o *.log
a.txt b.txt c.txt main.o output.log parser.o
$ rm !*
rm *.txt *.o *.log
In der Praxis benutze ich !* nicht so oft wie !$. Der Asterisk birgt immer das Risiko, als Pattern-Matching-Zeichen für Dateinamen interpretiert zu werden (falls Sie sich vertippen), sodass er nicht so viel sicherer ist als das Eintippen eines Musters wie *.txt von Hand.
Wäre es nicht toll, wenn Sie einige Zeichen eines Befehls eintippen könnten und der Rest würde dann spontan auftauchen, bereit zur Ausführung? Nun, das ist tatsächlich möglich. Diese flinke Eigenschaft der Shell wird als inkrementelle Suche bezeichnet und ist vergleichbar mit den interaktiven Vorschlägen, die von Suchmaschinen im Web angeboten werden. In den meisten Fällen ist die inkrementelle Suche die einfachste und schnellste Technik, um Befehle aus der History wieder hervorzuholen, und das gilt selbst für Befehle, die schon lange zurückliegen. Ich empfehle, sie unbedingt in Ihr Arsenal an Werkzeugen aufzunehmen:
Nehmen wir einmal an, Sie hätten vor einer Weile den Befehl cd $HOME/Finances/Bank eingegeben und wollten ihn nun noch einmal ausführen. Drücken Sie am Shell-Prompt Strg-R. Der Prompt verändert sich, um eine inkrementelle Suche anzuzeigen:
(reverse-i-search)`':
Beginnen Sie mit dem Eintippen des gewünschten Befehls. Geben Sie zum Beispiel c ein:
(reverse-i-search)`': c
Die Shell zeigt den neuesten Befehl an, der den String c enthält, und hebt hervor, was Sie bereits eingetippt haben:
(reverse-i-search)`': less /etc/hosts
Tippen Sie den nächsten Buchstaben ein, d:
(reverse-i-search)`': cd
Die Shell zeigt den neuesten Befehl an, der den String cd enthält, und hebt wieder hervor, was Sie getippt haben:
(reverse-i-search)`': cd /usr/local
Tippen Sie weiter und fügen Sie ein Leerzeichen und ein Dollarzeichen hinzu:
(reverse-i-search)`': cd $
Die Kommandozeile wird zu:
(reverse-i-search)`': cd $HOME/Finances/Bank
Dies ist der Befehl, den Sie haben wollten. Drücken Sie Enter, um ihn auszuführen, und Sie haben es mit fünf schnellen Tastendrücken geschafft.
Ich bin hier davon ausgegangen, dass cd $HOME/Finances/Bank der neueste passende Befehl in der History war. Doch was, wenn er es nicht ist? Was ist, wenn Sie einen ganzen Haufen von Befehlen eingegeben hatten, die den gleichen String enthalten? In diesem Fall hätte die gezeigte inkrementelle Suche einen anderen Treffer gezeigt, etwa diesen:
(reverse-i-search)`': cd $HOME/Music
Was nun? Sie könnten noch mehr Zeichen eingeben, um das Ergebnis auf den gewünschten Befehl einzugrenzen. Drücken Sie jedoch stattdessen ein weiteres Mal Strg-R. Damit wird die Shell veranlasst, zum nächsten passenden Befehl in der History zu springen:
(reverse-i-search)`': cd $HOME/Linux/Books
Drücken Sie erneut so lange Strg-R, bis Sie den gewünschten Befehl erreicht haben:
(reverse-i-search)`': cd $HOME/Finances/Bank
und drücken Sie dann Enter, damit er ausgeführt wird.
Hier sind einige weitere Tricks für die inkrementelle Suche:
Machen Sie sich umfassend mit der inkrementellen Suche vertraut. Sie werden schon bald Befehle in einer ungeheuren Geschwindigkeit finden.3
Es gibt diverse Gründe, um einen Befehl entweder beim Eintippen oder nach dem Ausführen zu bearbeiten:
In diesem Abschnitt zeige ich Ihnen drei Möglichkeiten, um einen Befehl zu bearbeiten und damit geschickter und schneller zu werden:
Cursor-Methode
Auch hier wieder die langsamste und am wenigsten leistungsfähige Methode, aber einfach zu erlernen.
Caret-Notation
Eine Form der History-Erweiterung.
Tastenkombinationen im Emacs- oder Vim-Stil
Leistungsfähige Methode zum Bearbeiten der Kommandozeile.
Wie zuvor empfehle ich, sich mit allen drei Methoden zu beschäftigen, damit Sie möglichst flexibel sind.
Drücken Sie einfach die Pfeil-nach-links- und Pfeil-nach-rechts-Tasten, um sich zeichenweise auf der Kommandozeile hin- und herzubewegen. Mit der Backspace- oder Löschtaste können Sie Text entfernen und dann Ihre Korrekturen eintippen. Tabelle 3-1 fasst diese und andere Standardtastendrücke zum Bearbeiten der Kommandozeile zusammen.
Das Hin- und Herbewegen des Cursors ist leicht, aber nicht besonders effizient. Es eignet sich am besten, wenn die Änderungen klein und einfach sind.
Tabelle 3-1: Cursor-Tastenbefehle für ein einfaches Kommandozeilen-Editing
Taste |
Aktion |
Pfeil-nach-links |
Ein Zeichen nach links bewegen. |
Pfeil-nach-rechts |
Ein Zeichen nach rechts bewegen. |
Strg + Pfeil-nach-links |
Ein Wort nach links bewegen. |
Strg + Pfeil-nach-rechts |
Ein Wort nach rechts bewegen. |
Home |
An den Anfang der Kommandozeile bewegen. |
Ende |
An das Ende der Kommandozeile bewegen. |
Backspace |
Ein Zeichen vor dem Cursor löschen. |
Entf |
Ein Zeichen unter dem Cursor löschen. |
Nehmen wir einmal an, Sie hätten versehentlich den folgenden Befehl ausgeführt, indem Sie jg statt jpg eingetippt haben:
$ md5sum *.jg | cut -c1-32 | sort | uniq -c | sort -nr
md5sum: '*.jg': No such file or directory
Um den Befehl richtig auszuführen, könnten Sie ihn aus der Befehls-History zurückholen, mit dem Cursor über den Fehler gehen und ihn beheben. Es gibt jedoch eine schnellere Möglichkeit, um dieses Ziel zu erreichen. Tippen Sie einfach den alten (falschen) Text, den neuen (korrigierten) Text und ein Paar aus Carets (^) ein, also so:
$ ^jg^jpg
Drücken Sie Enter, erscheint der korrekte Befehl und wird ausgeführt:
$ ^jg^jpg
md5sum *.jpg | cut -c1-32 | sort | uniq -c | sort -nr
...
Die Caret-Syntax, eine Art von History-Erweiterung, bedeutet: »Ersetze in dem vorhergehenden Befehl jg durch jpg.« Beachten Sie, dass die Shell hilfsbereit ist und den neuen Befehl vor der Ausführung ausgibt. Das ist das Standardverhalten für die History-Erweiterung.
Diese Technik ändert nur das erste Vorkommen des Quellstrings (jg) in dem Befehl. Enthielt Ihr ursprünglicher Befehl mehr als einmal den String jg, wird nur die erste Instanz in jpg geändert.
Leistungsfähigere Ersetzung mittels History-Erweiterung
Möglicherweise sind Sie vertraut mit der Verwendung der Befehle sed oder ed zum Ändern eines Quellstrings in einen Zielstring:
s/Quelle/Ziel/
Die Shell unterstützt eine ähnliche Syntax. Beginnen Sie mit einem Ausdruck für die History-Erweiterung zum Zurückholen eines Befehls, wie etwa !!. Fügen Sie dann einen Doppelpunkt hinzu und enden Sie mit einer Ersetzung im sed-Stil. Um zum Beispiel den vorherigen Befehl zurückzuholen und jg durch jpg (nur beim ersten Auftreten) zu ersetzen, wie es die Caret-Notation macht, führen Sie aus:
$ !!:s/jg/jpg/
Sie könnten mit jeder History-Erweiterung beginnen, mit der Sie möchten, wie etwa !md5sum, das den neuesten Befehl zurückholt, der mit md5sum beginnt, und die gleiche Ersetzung von jg durch jpg durchführen:
$ !md5sum:s/jg/jpg/
Diese Notation sieht vielleicht kompliziert aus, aber manchmal erreichen Sie damit schneller Ihr Ziel als mit anderen Techniken zum Bearbeiten der Kommandozeilen. Ganz genau erfahren Sie es, wenn Sie man history ausführen.
Die leistungsfähigste Methode, um eine Kommandozeile zu bearbeiten, setzt auf die vertrauten Tastaturbefehle, die durch Texteditoren wie Emacs und Vim inspiriert sind. Falls Sie sich bereits mit einem dieser beiden Editoren auskennen, können Sie in diesen Stil des Kommandozeilen-Editings direkt einsteigen. Falls nicht, finden Sie in Tabelle 3-2 die gebräuchlichsten Tastenkürzel zum Bewegen und Bearbeiten. Beachten Sie, dass die »Meta«-Taste bei Emacs üblicherweise Esc (gedrückt und losgelassen) oder Alt (gedrückt und gehalten) ist.
Shell-Vorgabe ist die Bearbeitung im Emacs-Stil, die ich empfehle, weil sie einfacher zu erlernen und anzuwenden ist. Sollten Sie den Vim-Stil bevorzugen, führen Sie den folgenden Befehl aus (oder fügen Sie ihn in Ihre $HOME/.bashrc-Datei ein):
$ set -o vi
Um einen Befehl mittels Vim-Tastenkürzeln zu bearbeiten, drücken Sie Enter, um den Bearbeitungsmodus zu starten. Dann nutzen Sie die Tastenkürzel aus der Spalte »Vim« in Tabelle 3-2. Mit diesem Befehl wechseln Sie wieder in die Emacsartige Bearbeitung:
$ set -o emacs
Und nun heißt es üben, üben, üben, bis Ihnen die Tastenkürzel (ob Emacs oder Vim) reibungslos von der Hand gehen. Vertrauen Sie mir, der Aufwand zahlt sich schnell durch eingesparte Zeit aus.
Tabelle 3-2: Tastenkürzel für das Editing im Emacs- oder Vim-Stil1
Aktion |
Emacs |
Vim |
Ein Zeichen vorwärts bewegen |
Strg-f |
h |
Ein Zeichen zurück bewegen |
Strg-b |
l |
Ein Wort vorwärts bewegen |
Meta-f |
w |
Ein Wort zurück bewegen |
Meta-b |
b |
An den Zeilenanfang bewegen |
Strg-a |
0 |
An das Zeilenende bewegen |
Strg-e |
$ |
Zwei Zeichen transponieren (vertauschen) |
Strg-t |
xp |
Zwei Wörter transponieren (vertauschen) |
Meta-t |
n/a |
Den ersten Buchstaben des nächsten Worts großschreiben |
Meta-c |
w~ |
Das ganze nächste Wort großschreiben |
Meta-u |
n/a |
Das ganze nächste Wort kleinschreiben |
Meta-l |
n/a |
Groß-/Kleinschreibung des aktuellen Zeichens ändern |
n/a |
~ |
Das nächste Zeichen wörtlich einfügen, einschließlich Steuerzeichen |
Strg-v |
Strg-v |
Um ein Zeichen vorwärts löschen |
Strg-d |
x |
Um ein Zeichen zurück löschen |
Backspace oder Strg-h |
X |
Ein Wort vorwärts ausschneiden |
Meta-d |
dw |
Ein Wort zurück ausschneiden |
Meta-Backspace oder Strg-w |
db |
Vom Cursor bis zum Zeilenanfang ausschneiden |
Strg-u |
d^ |
Vom Cursor bis zum Zeilenende ausschneiden |
Strg-k |
D |
Die ganze Zeile löschen |
Strg-e Strg-u |
dd |
Den zuletzt gelöschten Text einfügen (Yank) |
Strg-y |
p |
Den nächsten gelöschten Text einfügen (nach einem früheren Yank) |
Meta-y |
n/a |
Die vorherige Bearbeitungsoperation widerrufen |
Strg-_ |
u |
Alle bisherigen Bearbeitungen widerrufen |
Meta-r |
U |
Vom Einfüge- in den Befehlsmodus umschalten |
n/a |
Esc |
Vom Befehls- in den Einfügemodus umschalten |
n/a |
i |
Eine laufende Bearbeitungsoperation abbrechen |
Strg-g |
n/a |
Die Anzeige löschen |
Strg-l |
Strg-l |
1Aktionen, die mit n/a gekennzeichnet sind, besitzen kein einfaches Tastenkürzel, können aber möglicherweise mit einer längeren Abfolge von Tastenkürzeln ausgeführt werden.
Weitere Einzelheiten zum Bearbeiten im Emacs-Stil finden Sie im Abschnitt »Bindable Readline Commands« (https://oreil.ly/rAQ9g) von GNUs bash-Handbuch. Zum Bearbeiten im Vim-Stil erfahren Sie mehr im Dokument »Readline VI Editing Mode Cheat Sheet« (https://oreil.ly/Zv0ba).
Üben Sie die Techniken in diesem Kapitel, und Sie werden auf der Kommandozeile viel schneller werden. Speziell drei der Techniken hatten entscheidenden Einfluss darauf, wie ich Linux verwende, und ich hoffe, sie beeinflussen auch Sie auf positive Weise: