¿Cómo ejecutar comandos consecutivos desde el historial?

49

Supongamos que quiero ejecutar una secuencia de cuatro comandos que he ejecutado antes. Si el primero es 432 en el historial de comandos, entonces podría hacer:

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

Tengo curiosidad, ¿hay una manera más eficiente de lograr esto?

Eric Wilson
fuente
1
No publica esto como respuesta porque no ejecuta los comandos, pero puede escribir history -p \!43{2..5}para imprimir los comandos 432 a 435 en el terminal, adecuado para copiar / pegar posteriormente.
Comodín

Respuestas:

48

Si se refiere a comandos ejecutados recientemente, una forma más eficiente es hacer referencia a ellos con números negativos:

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

Además, una vez que lo haga, su última entrada del historial contendrá toda la cadena de comandos, por lo que puede repetirla con !!.


Editar: si aún no lo ha hecho, familiarícese con la gran función integrada fc, mencionada por Gilles . (Uso help fc.) Resulta que también puedes usar números negativos con él, por lo que puedes hacer lo mismo que arriba usando

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

Sin embargo, esto tiene una advertencia: después de esto, la evallínea se almacena en el historial como el último comando. Entonces, si ejecuta esto nuevamente, ¡caerá en un bucle!

Una forma más segura de hacerlo es usar el modo de fcoperación predeterminado : reenviar el rango seleccionado de comandos a un editor y ejecutarlos una vez que salga de él. Tratar:

 fc -4 -1

Incluso puede invertir el orden del rango de comandos: fc -1 -4

rozcietrzewiacz
fuente
Acabo de leer lo que había escrito ... LOL. En realidad, no estoy seguro acerca de reinvocar ( volver a invocar tal vez?), Pero gracias por contar :) Siempre aprecio correcciones.
rozcietrzewiacz
Scrabblefinder.com dice que reinvoke es una palabra válida de Scrabble. No hay nada más definitivo que eso. :)
BentFX
1
Con una buena respuesta como esta (+1), no importa cómo la deletree; especialmente porque ninguna forma de ortografía aparece en 3 diccionarios de inglés principales : Oxford, Camgridge, Merriam-Webster (iría por el guión)
Peter.O
34

Para ver un rango de comandos en el historial, use el fccomando incorporado :

fc -ln 432 435

Para ejecutarlos nuevamente:

eval "$(fc -ln 432 435)"
Gilles 'SO- deja de ser malvado'
fuente
44
Muy agradable. Sin embargo, tengo curiosidad, ¿por qué man fcno me da nada? ¿Qué significa fc? ¿Qué otras opciones hay?
Eric Wilson
2
@Eric Wilson ... escriba help fc... y también help help.... help: help [-dms] [pattern ...] Muestra información sobre los comandos incorporados.
Peter.O
Acabo de regresar aquí, buscando tu respuesta. ¡Esto realmente es un gran edificio! Especialmente cuando tiene su funcionalidad predeterminada: invocar un editor para modificar un rango de comandos que se reproducirán. Gracias Gilles
rozcietrzewiacz
1
Sin -lbandera, se ejecutará sin necesidad del mal eval.
Bernhard
1
@EricWilson Una búsqueda en Google me llevó al libro "Unix in a Nutshell" que dice " fcsignifica comando" o "comando fijo".
Slothworks
10

Hay una manera agradable y alternativa de ejecutar una serie de comandos en secuencia desde el historial de Bash: en
lugar de usar el sustituto del historial ( !432o !-4), puede buscar en el historial con Ctrl+ r, y una vez que haya encontrado el primer comando que desea ejecutar, presionar Ctrl+ o( operar-y-obtener-siguiente ) en lugar de la returntecla
Esto lanzará el comando y propondrá el siguiente del historial. Puede presionar Ctrl+otantas veces como desee y finalizar la secuencia con returnuna última, o Ctrl+cdetenerse sin iniciarla.

Cyril Chaboisseau
fuente
Hmm, después de golpearlo Ctrl-osolo genera un literal ^oy rompe mi (reverse-i-search). Tal vez hay algún otro entorno involucrado.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
8

Para ejecutar los comandos inmediatamente en lugar de editarlos, aquí hay una versión sintácticamente más delgada de la respuesta de Giles usando eval :

fc -e: 432 435

El argumento de dos puntos para -e es el bash noop, que tiene el efecto de omitir el paso "abrir en un editor" que fc quiere. Además, ahora el historial (reciente) contendrá los comandos reales del historial, en lugar de la instrucción eval.

usuario1543542
fuente
0

fc para bucle y xsel

Esto funciona bien cuando quiero concatenar y volver a ejecutar los últimos n comandos varias veces:

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})"
)

Entonces:

$ 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

O para comandos más grandes que pueden necesitar alguna edición:

fcn 3 1 >cmds.sh
vi cmds.sh
bash cmds.sh
bash cmds.sh
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente