Como executar comandos consecutivos da história?

49

Suponha que eu queira executar uma sequência de quatro comandos que eu executei antes. Se o primeiro for 432 no histórico de comandos, eu poderia fazer:

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

Estou curioso, existe uma maneira mais eficiente de conseguir isso?

Eric Wilson
fonte
11
Não postando isso como resposta, porque ele não executa os comandos, mas você pode digitar history -p \!43{2..5}para imprimir os comandos 432 a 435 no terminal, adequado para copiar / colar subsequente.
Curinga

Respostas:

48

Se se referir a comandos executados recentemente, uma maneira mais eficiente é referenciá-los com números negativos:

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

Além disso, depois de fazer isso, sua entrada no último histórico conterá toda a cadeia de comandos, para que você possa repeti-la !!.


Edit: Se você ainda não o conhece, familiarize-se com a excelente função incorporada fc, mencionada por Gilles . (Use help fc.) Acontece que você também pode usar números negativos com ele, para fazer o mesmo que acima, usando

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

Porém, isso tem uma ressalva: depois disso, a evallinha é armazenada no histórico como o último comando. Então, se você executar isso novamente, você entrará em um loop!

Uma maneira mais segura de fazer isso é usar o fcmodo de operação padrão : encaminhar o intervalo de comandos selecionado para um editor e executá-los quando você sair dele. Experimentar:

 fc -4 -1

Você pode até reverter a ordem do intervalo de comandos: fc -1 -4

rozcietrzewiacz
fonte
Acabei de ler o que tinha escrito ... LOL. Na verdade, não tenho certeza sobre reinvocar ( talvez recomeçar ?), Mas obrigado por informar :) Sempre aprecio correções.
rozcietrzewiacz
O Scrabblefinder.com diz que reinvocar é uma palavra válida do Scrabble. Não pode ser mais definitivo do que isso. :)
BentFX
11
Com uma boa resposta como esta (+1), não importa como você a soletra; especialmente porque nenhuma das formas de ortografia aparece nos 3 principais dicionários de inglês: Oxford, Camgridge, Merriam-Webster (eu
usaria
34

Para visualizar um intervalo de comandos no histórico, use o fccomando interno:

fc -ln 432 435

Para executá-los novamente:

eval "$(fc -ln 432 435)"
Gilles 'SO- parar de ser mau'
fonte
4
Muito agradável. Estou curioso, por man fcque não me dá nada. O que fcsignifica? Que outras opções existem?
Eric Wilson
2
@ Eric Wilson ... digite help fc... e também help help.... help: help [-dms] [pattern ...] Exibe informações sobre comandos internos.
Peter.O
Acabei de voltar aqui, procurando sua resposta. Este é realmente um ótimo recurso! Especialmente quando você é sua funcionalidade padrão - invocar um editor para modificar um intervalo de comandos a serem reproduzidos. Obrigado, Gilles.
rozcietrzewiacz
11
Sem -lbandeira, ele será executado sem necessidade do mal eval.
Bernhard
11
@EricWilson Uma pesquisa no Google me levou ao livro "Unix in a Nutshell" , que diz fcsignifica "comando de localização" ou "comando de correção".
Slothworks
10

Existe uma maneira agradável e alternativa de executar vários comandos em sequência no histórico do Bash: em
vez de usar o substituto do histórico ( !432ou !-4), você pode pesquisar no histórico com Ctrl+ re depois de encontrar o primeiro comando que deseja execute, pressione Ctrl+ o( opere e opte pelo próximo ) em vez da returntecla
Isso iniciará o comando e proporá o próximo do histórico. Você pode acertar Ctrl+oquantas vezes quiser e terminar a sequência com returnuma última, ou Ctrl+cparar sem iniciá-la.

Cyril Chaboisseau
fonte
Hmm, depois que eu acertei, Ctrl-oele produz um literal ^oe quebra meu (reverse-i-search). Talvez haja alguma outra configuração envolvida.
Ciro Santilli # 11/18
8

Para executar os comandos imediatamente, em vez de editá-los, eis uma versão sintaticamente mais fina da resposta do Giles usando eval :

fc -e: 432 435

O argumento de dois pontos para -e é o bash noop, que tem o efeito de pular a etapa "abrir em um editor" que o fc deseja. Além disso, agora o histórico (recente) conterá os comandos reais do histórico, em vez da instrução eval.

user1543542
fonte
0

fc para loop e xsel

Isso funciona bem quando eu quero concatenar e executar novamente os últimos n comandos várias vezes:

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

Então:

$ 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

Ou para comandos maiores que possam precisar de alguma edição:

fcn 3 1 >cmds.sh
vi cmds.sh
bash cmds.sh
bash cmds.sh
Ciro Santilli adicionou uma nova foto
fonte