Comment démarrer un terminal avec un certain texte déjà entré sur la ligne de commande?


25

Plutôt que de reformuler ma question, permettez-moi de vous décrire le cas d'utilisation souhaité:

Je crée un court shell-script pour exécuter la commande "gnome-terminal --someoptionflagname 'mon texte à publier'", et exécute ce script.

Gnome-terminal apparaît, avec une invite de ligne de commande suivie de mon texte.

c'est à dire: fields@mycomputer:/$ my text to be posted

Cela peut-il être fait?


Si ce bogue est jamais corrigé dans Ubuntu, vous devriez regarder dans cnee .
ændrük

@ ændrük Il est fixe et le nom du package est xneemaintenant.
dessert du

Réponses:


32

Vous pouvez le faire avec expect ( install ). Créez et rendez exécutable ~/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

et exécutez Gnome Terminal avec:

gnome-terminal -e ~/bin/myprompt

+1 pour l'utilisation d'Expect. Je l'utilise depuis des années pour automatiser beaucoup de choses.
Marco Ceppi

C'est cool. J'espérais qu'il y aurait une réponse simple (ish) basée sur la fonctionnalité par défaut de gnome-terminal, mais cela ressemble à la tâche.
emf

Celui-ci me dérange depuis si longtemps, je ne pouvais presque pas me rappeler quel était le cas d'utilisation prévu. Donc, pour clarifier: je voudrais faire quelque chose comme "gnome-terminal -e ls", mais le hic, c'est que la fenêtre reste ouverte. Donc, essentiellement des raccourcis pour ouvrir un terminal et exécuter des commandes shell. Cela clarifie-t-il les problèmes par rapport aux réponses d'Aendruk / MSW?
emf

1
Si tout ce que vous voulez, c'est que le terminal reste ouvert après une commande, il existe des solutions beaucoup plus simples .
ændrük

Merci beaucoup. J'ai réussi à intégrer cela dans un script shell qui appelle l'outil Pentaho d'intégration de données. Ensuite, j'ai ajouté l'appel à ce script au lanceur Unity dans 11.10, et cela fonctionne comme un charme.
bioShark

8

Si je comprends bien, vous voulez que votre première ligne d'entrée soit pré-remplie au contenu que vous passez sur la ligne de commande gnome-terminal.

Je ne sais pas comment faire exactement cela avec bash, mais voici quelque chose qui se rapproche. Dans votre ~/.bashrc, ajoutez la ligne suivante à la fin:

history -s "$BASH_INITIAL_COMMAND"

Exécutez gnome-terminal -x env BASH_INITIAL_COMMAND='my text to be posted' bashet appuyez sur Upà l'invite pour rappeler le texte.

Notez également que si vous mettez des set -o historycommentaires suivis à la fin de votre .bashrc, ils seront entrés dans l'historique au début de bash, vous pouvez donc les utiliser comme base pour les éditer en les atteignant avec la Upclé et en supprimant l'initiale #.


2
Bien que ce ne soit pas tout à fait la solution que je cherchais, c'est intéressant en soi.
emf

8

La suggestion d'ændrük est très bonne et a fonctionné pour moi, mais la commande est codée en dur dans le script, et si vous redimensionnez la fenêtre du terminal, cela ne fonctionne pas bien. En utilisant son code comme base, j'ai ajouté la possibilité d'envoyer au script myprompt la commande comme argument, et ce script gère correctement le redimensionnement de la fenêtre du 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

et exécutez Gnome Terminal avec:

gnome-terminal -e "~/bin/myprompt \"my text to be posted\""

1

La réponse d'ændrük est bonne, mais peut-être un peu lourde pour la tâche.

Voici un script qui écrit un script basé sur ses arguments

#!/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

Si vous n'avez pas fait beaucoup de programmation shell, il semble y avoir plus de magie ici qu'il n'y en a. Tout d'abord, je nomme un fichier temporaire pour contenir le script où $$est l'ID de processus du shell exécutant ce script. La /tmp/something.$$métaphore est utilisée dans le cas où deux instances de ce script sont exécutées en même temps, elles n'essaieront pas d'utiliser le même fichier temporaire.

La variable $SHELLest définie sur le nom du shell exécutant le script. Si vous utilisez / usr / bin / bash, vous aimeriez probablement que le mini-script l'utilise également.

C'est "$@"un idiome shell pour "interpoler tous mes arguments, en les citant si nécessaire". Cette syntaxe particulière provoque

script.sh 'my file' your\ file

pour interpoler les arguments en deux éléments

"my file" "your file"

au lieu des quatre qui $@donneraient

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

Les dernières lignes du script permettent à un gnome-terminal de démarrer le mini-script, puis de démarrer un shell interactif. Lorsque le gnome-terminal se ferme, le script temporaire est supprimé car le détritus n'est pas cool.

La dernière ligne ne fait pas partie du mini-script, elle démontre que le mini-script fonctionne. Si le script de 11 lignes ci-dessus se trouve dans un fichier appelé, rt.shle chmodrend exécutable et ensuite il est exécuté.

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

Le résultat de tout cela sera un terminal gnome qui démarre, affiche

hello world

sur sa première ligne puis démarre un shell interactif:

msw@myhost:~$

Je pense que votre script pourrait être réduit à gnome-terminal -x sh -c "echo hello world; bash", ce que je ne pense pas que la question demande.
ændrük

Ça a l'air cool. Pouvez-vous expliquer ce qui se passe ici?
emf

1
emfields: Je l'ai annoté pour vous.
msw

1
tu gères. merci pour les annotations, ce type d'aide rend l'accès aux scripts beaucoup plus accessible
emf

0

Les deux réponses que j'ai préféré résoudre sont celles utilisées expectet celle-ci où elles recommandent d'utiliser le --init-filedrapeau soit dans le shebang soit lors de l'exécution du terminal:

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

... et exécutez-le comme:

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 est probablement la meilleure solution (pour des raisons que je vais décrire), sauf que je ne peux pas contrôler si elle est installée dans mon environnement cible.

Le problème que j'ai rencontré avec les bash --init-fileet gnome-terminalles --commandcomme un hack pour résoudre ce problème est que le shell n'a pas accès à STDIN lors de l'exécution des scripts d'initialisation. Si, par exemple, je veux exécuter quelque chose qui nécessiterait une entrée utilisateur (ftp, telnet, etc.) mais laisser le shell parent fonctionner après cela ne fonctionnera pas; la seule exception que j'ai vue jusqu'à présent est ssh:

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

... mais ce dont j'ai besoin est plus compliqué que cet exemple de jouet. Quoi qu'il en soit, j'espère que le --init-filecontenu sera utile à tous ceux qui liront cette question.


-1

Vous pouvez utiliser les arguments -eou -xpour exécuter une commande dans un terminal nouvellement surgi, mais ce n'est pas exactement ce que vous voulez.


proche, mais pas tout à fait ce que je recherche. Un problème, dans ce cas, est que lorsqu'il est exécuté et terminé, le terminal se ferme immédiatement. Donc, disons que je veux un raccourci vers "ls ~ / notes", il se fermera avant que je puisse voir la sortie.
emf

S'il y avait une solution à cela, cela résoudrait la plupart des cas que je recherche.
emf
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.