Como iniciar um terminal com determinado texto já inserido na linha de comando?

25

Em vez de reformular minha pergunta, deixe-me descrever para você o caso de usuário desejado:

Eu crio um shell-script curto para executar o comando "gnome-terminal --someoptionflagname 'meu texto será postado'" e executo esse script.

O Gnome-terminal aparece, com o prompt da linha de comando seguido pelo meu texto.

ou seja: fields@mycomputer:/$ my text to be posted

Isso pode ser feito?

fem
fonte
Se esse bug já foi corrigido no Ubuntu, você deve consultar o cnee .
Octndrük # 8/10
@ ændrük Foi corrigido e o nome do pacote é xneeagora.
dessert

Respostas:

32

Você pode fazer isso com o expect ( instalar ). Crie e torne executável ~/bin/myprompt:

#!/usr/bin/expect -f

# Get a Bash shell
spawn -noecho bash

# Wait for a prompt
expect "$ "

# Type something
send "my text to be posted"

# Hand over control to the user
interact

exit

e execute o Gnome Terminal com:

gnome-terminal -e ~/bin/myprompt
ændrük
fonte
+1 para usar o Expect. Eu uso isso há anos para ajudar a automatizar muitas coisas.
Marco Ceppi
Isso é legal. Eu esperava que houvesse uma resposta simples (ish) com base na funcionalidade padrão do terminal gnome, mas parece que isso responde ao trabalho.
Em10/
Este está me incomodando há tanto tempo que eu quase não conseguia lembrar qual era o caso de uso pretendido. Então, para esclarecimentos: eu gostaria de fazer algo como "gnome-terminal -e ls", mas o problema é manter a janela aberta. Então, basicamente atalhos para abrir um terminal e executar comandos do shell. Isso esclarece os problemas versus as respostas de aendruk / msw?
emf
1
Se tudo o que você deseja é que o terminal permaneça aberto após um comando, existem soluções muito mais simples .
ændrük
Super, obrigada. Eu integrei isso com sucesso em um script de shell que chama de ferramenta de integração de dados Pentaho. Em seguida, adicionei a chamada a esse script ao lançador do Unity na 11.10, e funciona como um encanto.
precisa
8

Se bem entendi, você deseja que sua primeira linha de entrada seja preenchida com o conteúdo que você passa na linha de comando do gnome-terminal.

Eu não sei como fazer exatamente isso com o bash, mas aqui está algo que se aproxima. No seu ~/.bashrc, adicione a seguinte linha no final:

history -s "$BASH_INITIAL_COMMAND"

Execute gnome-terminal -x env BASH_INITIAL_COMMAND='my text to be posted' bashe pressione Upno prompt para recuperar o texto.

Observe também que, se você colocar os set -o historycomentários seguidos no final do seu comentário .bashrc, eles serão inseridos no histórico assim que o bash iniciar, para que você possa usá-los como base para editar, alcançando-os com a Uptecla e removendo a inicial #.

Gilles 'SO- parar de ser mau'
fonte
2
Embora não seja exatamente a solução que eu estava procurando, isso é interessante por si só.
emf
8

A sugestão de ændrük é muito boa e funcionou para mim, no entanto, o comando é codificado no script, e se você redimensionar a janela do terminal, ela não funcionará bem. Usando o código dele como base, adicionei a capacidade de enviar ao script myprompt o comando como argumento, e esse script manipula corretamente o redimensionamento da janela do terminal.

#!/usr/bin/expect

#trap sigwinch and pass it to the child we spawned
#this allows the gnome-terminal window to be resized
trap {
 set rows [stty rows]
 set cols [stty columns]
 stty rows $rows columns $cols < $spawn_out(slave,name)
} WINCH

set arg1 [lindex $argv 0]

# Get a Bash shell
spawn -noecho bash

# Wait for a prompt
expect "$ "

# Type something
send $arg1

# Hand over control to the user
interact

exit

e execute o Gnome Terminal com:

gnome-terminal -e "~/bin/myprompt \"my text to be posted\""
Gordon McCreight
fonte
1

A resposta de ændrük é boa, mas talvez um pouco pesada para a tarefa.

Aqui está um script que escreve um script com base em seus argumentos

#!/bin/sh
# terminal-plus-command: start a subordinate terminal which runs
# the interactive shell after first running the command arguments

tmpscript=/tmp/tmpscript.$$
echo "#!$SHELL" > $tmpscript
echo "$@" >> $tmpscript
echo exec "$SHELL" >> $tmpscript
chmod +x $tmpscript
gnome-terminal --command $tmpscript
rm -f $tmpscript

Se você não fez muita programação shell, parece haver mais mágica aqui do que existe. Primeiro, nomeio um arquivo temporário para armazenar o script, onde $$está o ID do processo do shell que está executando esse script. A /tmp/something.$$metáfora é usada caso duas instâncias desse script sejam executadas ao mesmo tempo, elas não tentarão usar o mesmo arquivo temporário.

A variável $SHELLé definida como o nome do shell que está executando o script. Se você usa / usr / bin / bash, provavelmente deseja que o mini-script também o use.

O "$@"é um idioma de shell para "interpolar todos os meus argumentos, citando-os se necessário". Essa sintaxe peculiar causa

script.sh 'my file' your\ file

interpolar os argumentos como dois elementos

"my file" "your file"

em vez dos quatro que $@renderiam

"my" "file" "your" "file"

As últimas linhas do script organizam um terminal gnome para começar a executar o mini-script e, em seguida, iniciar um shell interativo. Quando o gnome-terminal sai, o script temporário é removido porque o lixo não é legal.

A última linha não faz parte do mini-script, demonstra que o mini-script funciona. Se o script de 11 linhas acima estiver em um arquivo chamado, rt.shele o chmodtornará executável e, em seguida, será executado.

$ chmod +x rt.sh && ./rt.sh echo hello world

O resultado de tudo isso será um terminal gnome que inicia, exibe

hello world

em sua primeira linha e, em seguida, inicia um shell interativo:

msw@myhost:~$
msw
fonte
Acho que seu script pode ser reduzido a gnome-terminal -x sh -c "echo hello world; bash", o que não acho que a pergunta esteja sendo feita.
Octndrük 9/10/10
Isso parece legal. Você pode explicar o que está acontecendo aqui?
emf
1
emfields: eu anotei para você.
quer
1
você é demais. obrigado pelas anotações, esse tipo de ajuda torna a barreira à entrada com scripts muito mais acessível
emf
0

As duas respostas que eu mais gostei de resolver isso estão usando expecte essa é a que recomendam usar a --init-fileflag no shebang ou na execução do terminal:

#!/bin/bash --init-file
commands to run

... e execute-o como:

xterm -e /path/to/script
# or
gnome-terminal -e /path/to/script
# or
the-terminal -e bash --init-file /path/to/script/with/no/shebang

expect é provavelmente a melhor solução (por razões que descreverei), exceto que não posso controlar se ele está instalado no meu ambiente de destino.

O problema que encontrei com o bash --init-filee gnome-terminalo s --commandcomo um hack para resolver isso é que o shell não tem acesso ao STDIN durante a execução de scripts init. Se, por exemplo, eu quiser executar algo que exija entrada do usuário (ftp, telnet, etc), mas deixe o shell pai em execução depois, não funcionará; a única exceção que vi até agora é ssh:

xterm -e /bin/bash --init-file <(echo 'ssh -X some-machine')

... mas o que eu preciso é mais complicado do que este exemplo de brinquedo. De qualquer forma, espero que o --init-filematerial seja útil para quem lê esta pergunta.

Brian Vandenberg
fonte
-1

Você pode usar os argumentos -eou -xpara executar um comando dentro de um terminal recém-exibido, mas não é exatamente isso que você deseja.

Karl Bielefeldt
fonte
perto, mas não exatamente o que estou procurando. Um problema, nesse caso, é que, quando executado e finalizado, o terminal será fechado imediatamente. Então, digamos que eu queira um atalho para "ls ~ / notes", ele será fechado antes que eu possa visualizar a saída.
emf
Se houvesse uma solução para isso, resolveria a maioria dos casos que estou procurando.
Em10/