Wie führe ich aufeinanderfolgende Befehle aus der Historie aus?

49

Angenommen, ich möchte eine Folge von vier Befehlen ausführen, die ich zuvor ausgeführt habe. Wenn der erste 432 im Befehlsverlauf ist, könnte ich Folgendes tun:

$ !432; !433; !434; !435

Ich bin gespannt, gibt es einen effizienteren Weg, um dies zu erreichen?

Eric Wilson
quelle
1
Dies wird nicht als Antwort veröffentlicht, da die Befehle nicht ausgeführt werden. Sie können jedoch history -p \!43{2..5}die Befehle 432 bis 435 an das Terminal senden, um sie anschließend zu kopieren / einfügen.
Wildcard

Antworten:

48

Wenn es sich auf Befehle bezieht, die erst kürzlich ausgeführt wurden, besteht eine effizientere Möglichkeit darin, sie mit negativen Zahlen zu referenzieren:

!-4; !-3; !-2; !-1

Sobald Sie dies getan haben, enthält Ihr letzter Verlaufseintrag auch die gesamte Befehlskette, sodass Sie ihn mit wiederholen können !!.


Edit: Wenn Sie nicht bereits haben, machen Sie sich mit der großen eingebauten Funktion fc, durch Gilles erwähnt . (Verwendung help fc.) Es stellt sich heraus, dass Sie auch negative Zahlen verwenden können, sodass Sie dasselbe wie oben mit tun können

eval "`fc -ln -4 -1`"

Dies hat jedoch eine Einschränkung: Danach wird die evalZeile als letzter Befehl in der Historie gespeichert. Wenn Sie dies erneut ausführen, geraten Sie in eine Schleife!

Um dies sicherer zu machen, verwenden Sie den Standard- fcBetriebsmodus: leiten Sie den ausgewählten Befehlsbereich an einen Editor weiter und führen Sie ihn aus, sobald Sie ihn verlassen. Versuchen:

 fc -4 -1

Sie können die Reihenfolge der Befehle sogar umkehren: fc -1 -4

rozcietrzewiacz
quelle
Ich habe gerade gelesen, was ich geschrieben habe ... LOL. Eigentlich bin ich mir nicht sicher, ob ich es erneut aufrufen soll ( evtl. erneut aufrufen ?), Aber danke, dass du es mir mitteilst :) Ich freue mich immer über Korrekturen.
Rozcietrzewiacz
Scrabblefinder.com sagt, Reinvoke sei ein gültiges Scrabble-Wort. Definitiver geht es nicht. :)
BentFX
1
Bei einer guten Antwort wie dieser (+1) spielt es keine Rolle, wie Sie sie buchstabieren. Zumal keine der beiden Schreibweisen in drei großen englischen Wörterbüchern vorkommt: Oxford, Camgridge, Merriam-Webster (ich würde mich für den Bindestrich entscheiden)
Peter.O
34

Verwenden Sie den integrierten fcBefehl, um eine Reihe von Befehlen im Verlauf anzuzeigen :

fc -ln 432 435

Um sie erneut auszuführen:

eval "$(fc -ln 432 435)"
Gilles 'SO - hör auf böse zu sein'
quelle
4
Sehr schön. Ich bin allerdings neugierig, warum man fcgibst du mir nichts? Was bedeutet fcstehen? Welche anderen Möglichkeiten gibt es?
Eric Wilson
2
@Eric Wilson ... tippehelp fc ... und auch help help.... help: help [-dms] [pattern ...] Zeigt Informationen zu eingebauten Befehlen an.
Peter.O
Ich bin gerade hierher zurückgekommen und habe nach deiner Antwort gesucht. Das ist wirklich ein tolles eingebautes! Insbesondere, wenn Sie die Standardfunktionalität verwenden: Aufrufen eines Editors zum Ändern einer Reihe von Befehlen, die wiedergegeben werden sollen. Danke, Gilles.
Rozcietrzewiacz
1
Ohne -lFlag wird es ausgeführt, ohne das Böse zu brauchen eval.
Bernhard
1
@EricWilson Eine Google-Suche führte mich zum Buch "Unix in a Nutshell", in dem fc"find command" oder "fix command" steht.
Faultiere
10

Es gibt eine nette und alternative Möglichkeit, eine Reihe von Befehlen nacheinander aus dem Bash-Verlauf auszuführen:
Anstatt den Verlauf als Ersatz ( !432oder !-4) zu verwenden, können Sie den Verlauf mit Ctrl+ durchsuchen rund sobald Sie den ersten gewünschten Befehl gefunden haben Führen Sie aus, drücken Sie Ctrl+ o( Operate-and-Get-Next ) anstelle der returnTaste.
Dadurch wird der Befehl gestartet und der nächste Befehl aus dem Verlauf vorgeschlagen. Sie können Ctrl+oso oft drücken, wie Sie möchten, und die Sequenz entweder mit returnfür eine letzte Ctrl+cbeenden oder anhalten, ohne sie zu starten.

Cyril Chaboisseau
quelle
Hmm, nachdem ich darauf geklickt habe, Ctrl-owird nur ein Literal ausgegeben ^ound mein Wort gebrochen (reverse-i-search). Vielleicht gibt es eine andere Einstellung.
Ciro Santilli am
8

Um die Befehle sofort auszuführen, anstatt sie zu bearbeiten, ist hier eine syntaktisch schlankere Version von Giles answer using eval :

fc -e: 432 435

Das Doppelpunktargument für -e ist der Bash-Noop, der bewirkt, dass der von fc gewünschte Schritt "In einem Editor öffnen" übersprungen wird. Außerdem enthält der (aktuelle) Verlauf jetzt die tatsächlichen Befehle aus dem Verlauf und nicht mehr die eval-Anweisung.

user1543542
quelle
0

fc für Schleife und xsel

Dies funktioniert gut, wenn ich die letzten n Befehle mehrmals verketten und erneut ausführen möchte:

fcn() (
  from="${1:-2}"
  to="${2:-1}"
  if [ "$from" -ne "$to" ]; then
    for i in `seq "$from" -1 "$(($to + 1))"`; do
      printf "$(fc -ln -${i} -${i}) && "
    done
  fi
  printf "$(fc -ln -${to} -${to})"
)

Dann:

$ echo a
a
$ echo b
b
$ echo c
c
$ fcn 3 1 | xsel -b
$ # Paste.
$  echo a &&  echo b &&  echo c
a
b
c
$ # Paste again if you feel like it.
$  echo a &&  echo b &&  echo c
a
b
c

Oder für größere Befehle, die möglicherweise bearbeitet werden müssen:

fcn 3 1 >cmds.sh
vi cmds.sh
bash cmds.sh
bash cmds.sh
Ciro Santilli ist ein Schauspieler
quelle