Qual é a maneira mais fácil de executar texto da cauda na linha de comando?

10

Às vezes, estou trabalhando em uma nova caixa (ubuntu) e digito git e sou alertado:

The program 'git' is currently not installed.  You can install it by typing:
apt-get install git-core

Se isso acontecer, sei que posso pegar a última linha fazendo algo como:

!! 2>&1 | tail -n 1

Mas como eu poderia executar o resultado disso ( apt-get install git-core ) com mais facilidade?

Eu sei que posso fazer

'!! 2>&1 | tail -n 1'

mas existe também uma maneira de realmente enviar a saída e executá-la? Isso não parece funcionar:

!! 2>&1 | tail -n 1 | sh

Além disso, a parte 2>&1 é um pouco trabalhosa, por isso, seria curioso se houvesse uma maneira mais fácil de fazer isso acontecer também.

Editar

Também seria aceitável salvar isso em uma variável de alguma forma e, em seguida, executar a variável:

!! 2>&1 | tail -n 1 | (store as $mycmd)
$mycmd

Mas não tenho certeza se conheço uma maneira de canalizar stdout para uma variável, pelo menos não com a variável do lado direito do comando.

    
por cwd 04.04.2012 / 21:36

4 respostas

8

Quando você digita um comando que não existe no seu sistema, o bash executa a função command_not_found_handle() . Nesta função há uma chamada para o script /usr/lib/command-not-found que imprime mensagens.

Ubuntu 12.04

Meu primeiro palpite para alterar a origem deste script para imprimir mensagens para stdout em vez de stderr , mas quando eu estava lendo a fonte do script, descobri que você pode configurá-lo para perguntar se deseja instalar o pacote ausente .

Se você exportar a variável COMMAND_NOT_FOUND_INSTALL_PROMPT , será solicitado que você instale o pacote ausente:

pbm@ubuntu:~$ git
The program 'git' is currently not installed.  You can install it by typing:
sudo apt-get install git
pbm@ubuntu:~$ export COMMAND_NOT_FOUND_INSTALL_PROMPT=""
pbm@ubuntu:~$ git
The program 'git' is currently not installed.  You can install it by typing:
sudo apt-get install git
Do you want to install it? (N/y)y
sudo apt-get install git
[sudo] password for pbm: 

Versões mais antigas do Ubuntu

Infelizmente não há COMMAND_NOT_FOUND_INSTALL_PROMPT , por isso posso encontrar algumas outras opções:

1) Instale o pacote a partir de 12.04 - não deve ser o problema - são apenas alguns scripts em Python, então deve funcionar (não testado!).

2) Altere stderr para stdout . Para isso, edite o arquivo /usr/lib/python2.7/dist-packages/CommandNotFound/CommandNotFound.py e altere stderr para stdout nas linhas 237 e 240.

Depois disso, você pode usá-lo desta maneira:

pbm@ubuntu:~$ git
The program 'git' is currently not installed.  You can install it by typing:
sudo apt-get install git
pbm@ubuntu:~$ 'git'
//Installation begins

Se você adicionar a opção -y ao comando apt-get nas linhas 237 e 240, também poderá usar a sintaxe !! | sh .

3) Você também pode modificar este script da linha 242 desta forma:

print >> sys.stderr, _("You can install it by typing:")
f = open("%s/.install-missing" % os.path.expanduser('~'),'w')
print >> sys.stderr, "sudo apt-get install %s" % packages[0][0]
print >> f, "sudo apt-get install %s" % packages[0][0]
f.close()

Desta forma você obterá seu comando no arquivo ~/.install-missing , então você pode criar um alias:

alias im="chmod +x ~/.install-missing; ~/.install-missing"

Se você chamar im package será instalado.

    
por 04.04.2012 / 23:03
3

Você estava no caminho certo com:

!! 2>&1 | tail -n 1 | sh

... mas falta uma opção para sh . Considere:

!! 2>&1 | tail -n 1 | sh -s

E como provavelmente você precisa de acesso root para executar o apt-get, considere:

!! 2>&1 | tail -n 1 | sudo sh -s
    
por 06.04.2012 / 03:05
1

Você pode fazer algo assim:

!! 2>&1 | tail -n 1 > /tmp/cmd; bash /tmp/cmd; rm /tmp/cmd

Os programas interativos parecem não funcionar bem com o piping porque espera uma entrada, 'Y' neste caso, mas o descritor de arquivo stdin é fechado assim que o primeiro comando termina.

    
por 05.04.2012 / 00:02
0

Você pode usar uma variável, eval e substituição de comando, acredito (embora não tenha certeza de como isso seria seguro):

TEST_VAR=$(!! 2>&1 | tail -n 1); eval $TEST_VAR

Estou disposto a estar errado com o que foi dito acima. Estou testando isso em uma máquina da Red Hat com um comando echo em vez de sugerir automaticamente a conclusão do bash, mas o princípio deve ser o mesmo.

No final do dia, seria mais rápido digitar apenas o aptitude install git ...

    
por 05.04.2012 / 18:17