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

10

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

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

Se isso acontecer, eu 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) mais facilmente?

Eu percebo que eu poderia fazer

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

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

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

Além disso, a 2>&1parte é um pouco complicada, então eu ficaria curioso para saber se existe uma maneira mais fácil de fazer isso acontecer.

Editar

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

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

Mas também não tenho certeza de que conheço uma maneira de stdoutinserir uma variável, pelo menos não com a variável no lado direito do comando.

cwd
fonte

Respostas:

8

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

Ubuntu 12.04

Minha primeira suposição a fonte mudança desse script para imprimir mensagens de stdoutvez stderr, mas fonte quando eu estava lendo de script que eu descobri que você pode configurá-lo para apenas perguntar se você deseja instalar o pacote faltando.

Se você exportar variável, COMMAND_NOT_FOUND_INSTALL_PROMPTvocê será solicitado a instalar 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 anteriores do Ubuntu

Infelizmente não há, COMMAND_NOT_FOUND_INSTALL_PROMPTpara que eu possa encontrar algumas outras opções:

1) Instale o pacote a partir do 12.04 - não deve ser o problema - são apenas alguns scripts em Python, portanto devem funcionar (não testados!).

2) Mude stderrpara stdout. Para fazer isso, edite o arquivo /usr/lib/python2.7/dist-packages/CommandNotFound/CommandNotFound.pye altere stderrpara stdoutnas 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 -yopção de apt-getcomando nas linhas 237 e 240, também poderá usar a sintaxe !! | sh.

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

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

Dessa forma, você receberá seu comando no arquivo ~/.install-missing, portanto, você pode criar um alias:

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

Se você chamar o impacote será instalado.

pbm
fonte
Hmm, isso parecia realmente bom, mas na verdade não parece funcionar na 11,10 onírica, /usr/lib/command-not-foundmas não tem referência a COMMAND_NOT_FOUND_INSTALL_PROMPT- pensamentos?
Cwd
Ok, parece que esse é um recurso que fará parte do 12.04 preciso, ( package-import.ubuntu.com/diffs/command-not-found ). Acho que ainda preciso de uma solução para versões anteriores.
Cwd
@cwd: Eu atualizei a minha resposta ...
PBM
3

Você estava no caminho certo com:

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

... mas você está perdendo uma opção para sh . Considerar:

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

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

!! 2>&1 | tail -n 1 | sudo sh -s
ctt
fonte
Isso não funciona. sh e sh -s fazem a mesma coisa, pelo menos neste caso.
Deepak Mittal
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 a tubulação, porque espera uma entrada 'Y' neste caso, mas o descritor de arquivo stdin é fechado assim que o primeiro comando é concluído.

Deepak Mittal
fonte
0

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

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

Estou disposto a provar que estou errado com o exposto acima. Estou testando isso em uma máquina Red Hat com um echocomando, 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 o aptitude install git ...

webtoe
fonte