Como desfazer alterações no histórico de comandos?

12

Nos sistemas UNIX, você pode pressionar as setas superior e inferior para navegar pelos comandos anteriores. Isso é extremamente útil.

Às vezes, subo e encontro um comando que quero usar novamente, mas com algumas variações. Se eu fizer essas alterações, não tenho como recuperar o comando original, a menos que faça o check-in history.

Existe alguma maneira de "desfazer" as alterações no comando no histórico acessado por meio de chaves?

Minha solução atual é acrescentar #a ao comando. Dessa forma, o comando atual é executado como um comentário, para que nada aconteça. Então, posso navegar novamente pelos comandos com as teclas. O problema é que o comando que eu estava usando pode ser muito distante na lista, então subir novamente duzentas vezes é um pouco. Control + R também não é uma solução, pois posso não me lembrar exatamente o que estava procurando.

Exemplo

Digitei o seguinte "50 comandos atrás":

ls -l /etc/httpd/conf/

Agora fui até essa linha e mudei para

ls -l /etc/init.d/

mas não pressione enter. Agora, quero voltar ao ls -l /etc/httpd/conf/assunto.

Meu ambiente

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm
fedorqui
fonte
O fato de o histórico de comandos ser alterado provavelmente é um recurso (incorreto) do shell que você está usando. Por kshexemplo, você pode editar entradas do histórico e invocá-las sem excluir a "versão anterior" da entrada; você tem todos os comandos chamados disponíveis.
Janis
Com "muda", quero dizer que: dado um comando anterior que eu mudei depois de alcançá-lo com as setas, se eu subir e descer com as setas, o comando antigo não mostrará como era, mas como modifiquei isto. Obviamente, se eu digitar "enter" executando um comando, esse comando antigo será como era inicialmente; mas é exatamente isso que estou tentando evitar e procurando uma maneira de "redefinir" o comando para seu valor inicial.
Fedorqui
1
Também neste caso, ksho comportamento de difere aqui, ao que parece. E as opções de edição do seu histórico também dependem do modo de edição escolhido. No kshmodo vi, por exemplo, a entrada antiga não é substituída e também posso emitir um comando desfazer, como em vi, com 'u'.
Janis
Uhms, isso parece muito promissor. Agora, estou trabalhando no Bash e atualmente não estou pensando em mudar para ksh, mas é bom saber que isso existe lá.
Fedorqui
Gostaria de saber onde o bash armazena o histórico recente de comandos antes de gravar no arquivo de histórico quando o shell estiver fechado. Pode ajudar a determinar se isso é possível. Qualquer pessoa? Eu pensei que poderia estar em uma das variáveis ​​de shell, mas não tenho tempo para examinar o manual agora.
iyrin

Respostas:

10

Desde que você tenha editado uma entrada do histórico, mas Enterainda não tenha pressionado , para voltar à entrada original, pressione repetidamente Ctrl+ _- o undocomando - até que não faça mais alterações. Você voltou à entrada original.

Gilles 'SO- parar de ser mau'
fonte
5

Reverta ao comando original quando tiver feito várias alterações na linha:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

Mé a meta-chave, que é altrpara mim.


Informações gratuitas, mas úteis

Quando você ter executado um comando como OP tinha feito anteriormente (isso acontece), não há nada para "desfazer", porque os comandos são tratados e lembrado pelo GNU Readline biblioteca e são não escrito para$HISTFILE até as saídas de fachada. A razão de eu falar isso é porque você pode não apenas grepo $HISTFILEcomo se poderia esperar e pode não ser ideal para sair do shell.

Então, aqui estão algumas opções para evitar que você role de volta através de todos os comandos de linha de leitura anteriores.

Se você se lembrar de alguns dos comandos , pressione ctrl+ re digite o que você lembra para pesquisar nos comandos anteriores que contêm essa sequência. Pressionar ctrl+ rnovamente exibirá a próxima mais recente, pesquisando para trás.

Por exemplo, digite ls -lem seguida, ctrl+ rtantas vezes quanto for preciso para encontrar o comando anterior que você procura. Se você passar o mouse, ctrl+ sprocurará a partir da posição atual.

O fccomando bash builtin é útil para listar os números de índice juntamente com os comandos readline anteriores.

fc -l -100 listará os 100 comandos anteriores na linha de leitura.

Além disso, se o OP souber que está procurando um ls -lcomando anterior , ele poderá canalizar a saída para grep:fc -l -100 | grep 'ls -l'

Isso deve gerar uma lista de ls -lcomandos anteriores precedidos por um número de índice. A saída é assim:
2065 ls -l

Agora você pode usar o designador de evento !nonde nestá o número do índice. Neste exemplo, a execução !2065será expandida para ls -l.


Embora isso não ajude após o fato, qualquer pessoa que queira preservar o histórico recente de comandos ao modificar comandos anteriores deve ver a HISTORY EXPANSIONseção man bash. Aqui estão alguns métodos alternativos para modificar comandos antigos sem substituir o histórico.

A Event Designatorsseção mostra como você pode editar facilmente a sequência do comando usado mais recentemente.

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

Exemplo:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

Os comandos mais recentes agora mostrarão:

echo foo
echo bar

O exemplo acima também explica como usar sedpara substituir uma sequência em um designador de evento.

!-n    Refer to the current command minus n.

Portanto, se houver 3 comandos no histórico echo foo, você usaria:
!-3:s/foo/bar

Observe que os designadores de eventos aparecerão no seu histórico como o comando executado, neste caso echo bar. Não aparecerá no histórico como !-3:s/foo/bar.

Apenas lançando isso lá fora, como parece intimamente relacionado, mesmo que seja mais um "não faça" do que a solução "desfazer" que o OP está procurando.

iyrin
fonte
Isso é legal, muito obrigado pelas informações detalhadas. Estou aceitando a resposta de Gilles, pois faz exatamente o que estou procurando, enquanto aqui você assume que sei muitas coisas sobre o comando que quero refazer, o que nem sempre é o caso.
Fedorqui #
Sim, eu concordo. Seria ótimo se esse recurso de desfazer fosse estendido aos comandos anteriormente inseridos de alguma forma.
Iyrin