Existe um atalho para executar uma série de comandos no histórico do bash?

20

Suponha que eu tenha o seguinte exemplo trivial no meu history:

...
76 cd ~
77 ./generator.sh out.file
78 cp out.file ~/out/
79 ./out/cleaner.sh .
80 ls -alnh /out
...

Se eu quisesse executar comandos 77, 78e 79em um comando, existe um atalho para isso? Eu tentei !77 !78 !79, o que simplesmente colocará todos eles em uma única linha para executar.

MrDuk
fonte
9
Está !77 ; !78 ; !79bem?
thrig
11
Eu acho que qualquer coisa aquém de linha de escrita por linha é ok, mas estava esperando por algo um pouco mais concisa (ao longo das linhas de !77-79)
MrDuk
11
@ MrDuk, garoto, demorei um pouco para lembrar. Veja minha resposta atualizada para a solução muito concisa ! :)
Curinga
É mágico! :)
MrDuk 24/10

Respostas:

28

EDIT: Você pode fazer isso de maneira compatível com POSIX com a ferramenta de comando fixfc :

fc 77 79

Isso abrirá seu editor (provavelmente vi) com os comandos 77 a 79 no buffer. Quando você salvar e sair ( :x), os comandos serão executados.


Se você não deseja editá-los e com certeza sabe quais comandos está chamando, pode usar:

fc -e true 77 79

Isso é usado truecomo um "editor" para editar os comandos, portanto, ele sai sem fazer nenhuma alteração e os comandos são executados como estão.


RESPOSTA ORIGINAL:

Você pode usar:

history -p \!{77..79} | bash

Isso pressupõe que você não esteja usando aliases ou funções ou variáveis ​​presentes apenas no ambiente de execução atual, pois é claro que elas não estarão disponíveis no novo shell que está sendo iniciado.


Uma solução melhor (obrigado Michael Hoffman por me lembrar nos comentários) é:

eval "$(history -p \!{77..79})"

Um dos muito poucos casos em que evalé realmente apropriado!


Veja também:

Curinga
fonte
2
Isso não funcionará corretamente se algum dos comandos alterar o ambiente de execução atual, por exemplo, alterando uma variável ou executando a cd, mas esse é um caso extremo.
G-Man diz 'Reinstate Monica'
3
eval "$(history -p \!{77..79})"Deveria trabalhar.
Michael Hoffman
11
@ MichaelHoffman, eu pensei nisso e pensei que tinha tentado, mas acabei de perceber que deixei de citar! D'oh! Não é à toa que não funcionou ... editando a resposta agora.
Curinga
14

Resposta simples: em vez de !77 !78 !79,

  • digite !77; !78; !79para fazer o que parece estar tentando fazer - execute o comando 77 e, em seguida, o comando 78 e, em seguida, o comando 79, incondicionalmente ou
  • digite !77 && !78 && !79 para executar o comando 77 e verifique se foi bem-sucedido. E então, se o comando 77 tiver êxito, execute o comando 78. E, se o comando 78 tiver êxito, execute o comando 79.

Resposta ligeiramente mais inteligente (se você estiver em uma janela do tipo terminal):

  • Descubra qual número de comando será o próximo comando digitado.
    • É possível incluir isso no seu prompt; Eu acredito que é incluindo \!no seu PS1.
    • Ou veja sua lista de histórico. Se a última entrada for 82 history, seu próximo comando será 83.
  • Subtraia 83−77 = 6.
  • Digite !-6. Isso reexecutará o comando 77.
  • Selecione !-6, copie e cole. Como sua reexecução do comando 77 ( ./generator.sh) foi o comando 83, agora você está no comando 84, então !-6reexecutará o comando 78.
  • Repita a colagem !-6conforme desejado.
G-Man Diz 'Reinstate Monica'
fonte