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?


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


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

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.


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.