Rappelez-vous une commande à moitié tapée pendant que je vérifie quelque chose

96

Je me trouve souvent dans la position suivante: j'ai commencé à taper une longue commande à l'invite bash, mais au milieu, je découvre que je dois vérifier quelque chose avec une autre commande. C'est un problème lorsque je suis à la console (pas de X), ce qui est souvent le cas, car je n'ai alors que les moyens insatisfaisants pour le faire, que je connais:

  • Appuyez sur ctrl+ alt+ F2et connectez-vous à une autre console virtuelle et découvrez ce que je voulais, puis revenez en arrière et continuez
  • ctrl+ a, tapez echo + space+ enter, découvrez ce que je voulais, appuyez jusqu'à ce que je trouve ma commande, ctrl+ a, delx 5, ctrl+ eet continuez
  • Mettez en surbrillance ce que j'ai tapé jusqu'à présent avec ma souris (si gpm est en cours d'exécution, ce qui est généralement le cas), appuyez sur ctrl+ cpour l'interrompre, découvrez ce que je voulais en faisant attention de ne pas utiliser ma souris pour mettre en évidence des éléments, puis appuyez sur le bouton central de la souris. sur une nouvelle invite et continuez
  • Priez les dieux de la ligne de commande pour que la commande à moitié écrite n'ait pas d'effet négatif, mais simplement échoue, et appuyez avec précaution sur entrée, puis découvrez ce que je voulais, appuyez sur la touche de haut en bas jusqu'à ce que je récupère ma commande, puis continuez.
  • Aller dans ma machine à voyager dans le temps, remonter dans le temps et me rappeler de démarrer écran avant de commencer à taper une commande, revenir au présent, appuyer sur ctrl+ a c, trouver ce que je voulais, appuyer sur ctrl+ a ctrl+aet continuer

Ce que je veux savoir, c'est s'il existe un moyen plus élégant de le faire. Une sorte de commande de sous-coque ou similaire?

Je suis surtout intéressé par les méthodes qui ne nécessitent aucune préparation ou configuration pour fonctionner.

Lauritz V. Thaulow
la source

Réponses:

67

Une version un peu plus rapide de alex de Ctrl + A Ctrl+ K(qui se déplace à l'avant de la ligne, puis coupe tout en avant) est d'utiliser seulement Ctrl+ U, qui coupe vers l' arrière sur bash, et toute la ligne (quelle que soit votre position actuelle) sur zsh. Ensuite, vous utilisez Ctrl+ Ypour le coller à nouveau

Michael Mrozek
la source
1
En testant cela, je conclus que Ctrl + U ne recule pas et ne coupe pas en avant, mais plutôt en arrière. Le fait de placer le curseur au milieu de la commande laisse ce qui se trouve derrière sur la ligne de commande. Une amélioration de 33% par rapport à la solution de @ alex cependant, car elle enregistre une frappe au clavier.
Lauritz V. Thaulow
2
@Lazyr Oh, c'est vrai; sur zshelle coupe toute la ligne, mais sur bashelle coupe en arrière. Je n'avais jamais remarqué cette différence auparavant
Michael Mrozek
2
Oh, je ne savais pas que Ctrl + U mettait aussi du texte pour tuer le tampon. Bon à savoir! :)
alex
1
^U ^Kaura le même effet que ^A ^Kmais est légèrement plus ergonomique et nettement plus pratique sous screen.
Intuition le
52

Faites ctrl-A pour vous rendre au début de la ligne, ajoutez un hachage et appuyez sur la touche Entrée - de cette manière, il restera dans l’historique des commandes sous forme de commentaire et vous pourrez y revenir avec le curseur haut.

EDIT: je viens de remarquer que cette variante est un peu plus élégante sur votre # 2;)

Jamespo
la source
1
Oui, et pourquoi je n'y avais pas pensé? Je vous remercie!
Lauritz V. Thaulow
1
Je dois lire avant de poster ma propre réponse. James a tout à fait raison.
Sean C.
4
Notez que cela ne fonctionnera pas dans cshou zshparce qu'ils n'autorisent pas les commentaires dans le shell interactif. En zshvous devez activer l'option appropriée: setopt interactive_comments.
Sam Hocevar
1
@Sam Oui, mais ": command" a le même effet (":" = la commande null)
barrycarter Le
6
@barrycarter: non, :devrait être considéré comme nocif à cette fin et ne jamais être suggéré. Il exécutera tout après un point-virgule, des backticks internes, etc. avec tous les effets secondaires associés.
Sam Hocevar
29

Hit Ctrl+A, Ctrl+Kpour aller au début de la ligne et supprimer (kill) jusqu'à la fin. Ensuite, faites votre recherche et, lorsque vous Ctrl+Yêtes prêt à continuer, appuyez sur le bouton pour remettre votre ligne sauvegardée.

alex
la source
3
Ah, maintenant cela ressemble plus à ce que j'avais en tête. Et je le fais tout le temps dans Emacs, aurait dû penser à faire la même chose sur la ligne de commande.
Lauritz V. Thaulow
13

En zsh, je tape Ctrl+ Zpour «suspendre» la commande que je tape et saisis une autre commande. Après avoir exécuté cette commande (ou l'avoir annulée avec Ctrl+ C), la commande suspendue revient pour édition (même en se rappelant la position du curseur). Pour plus de commodité, si la ligne de commande est vide lorsque je tape Ctrl+ Z, la touche appelle la fonction bgintégrée (un double Ctrl+ Zenvoie donc une commande en cours d'exécution directement à l'arrière-plan).

fancy-ctrl-z () {
  emulate -LR zsh
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z'          fancy-ctrl-z

Je ne sais pas comment faire quelque chose de similaire à Bash.

Dans n'importe quel shell, vous pouvez utiliser la méthode peu technique consistant à ajouter un #au début de la ligne en cours .

Gilles
la source
2
votre fonction est admirable, mais saviez-vous qu’il zshexiste déjà une fonction intégrée ? Cela s'appelle push-lineet tout ce que vous avez à faire est d'utiliser bindkeypour y arriver.
Caleb
@Caleb: Je ne sais pas pourquoi je l'utilise push-inputplutôt push-linequ'ici, push-linesemble-t-il plus approprié (peut-être que les anciennes versions de zsh ne l'étaient push-input?). Mais ce n'est pas un remplacement pour le reste de la fonction.
Gilles
Autant que je sache, la seule différence est l’effet de liaison identique à l’arrière-plan d’un travail en cours d’exécution. Est-ce que je manque quelque chose?
Caleb
1
@Caleb: Non, il est juste que je trouve la combinaison des deux à la fois pratique ( push-linene sert à rien sur une ligne vide, ayant bgsur Ctrl+Zseulement est utile quand je viens avec ce processus suspendu Ctrl+Z) et mnémoniques (je suis soit le processus semi- finition ou la ligne de commande partielle).
Gilles
3
@Caleb push-inputsuspend tout le tampon d'entrée, alors que push-linene suspend que la ligne en cours. Si je tape une commande multiligne, je veux suspendre toute la commande, donc push-inputc'est la bonne. Je trouve push-inputplus souvent utile que push-line(si je veux retarder une ligne dans une mémoire tampon multiligne, je peux simplement naviguer jusqu'au début de la ligne et insérer une nouvelle ligne), je me demande donc pourquoi push-linela liaison par défaut a été obtenue push-input.
Gilles
13

En bash, tapez simplement Alt+ #.

Ensuite, lorsque vous êtes prêt, appuyez sur Uppuis sur Alt+ #.

Le premier met un #en début de ligne pour le transformer en commentaire, puis accepte la ligne, comme si vous aviez appuyé Enter.

Ensuite, lorsque vous le faites une seconde fois, il voit que la ligne a déjà un a #au début, donc il la supprime et l’accepte, en vous sauvant à nouveau la Enterclé.

Si la deuxième fois insère simplement une autre #, vous devez taper Alt+ - Alt+ à la #place.

Vous pouvez faire de même avec zsh en mettant

bindkey -M emacs '\e#' pound-insert

dans votre ~ / .zshrc.

Ou, si vous utilisez des liaisons vi, vous pouvez taper à #partir du mode commande à la fois en bash et en zsh.

Mikel
la source
2
Cela ne fonctionne pas pour moi, la deuxième commande destinée à supprimer le # ajoute simplement plus de # au début.
Lauritz V. Thaulow
1
Le premier fonctionne-t-il? Quelle version de bash utilisez-vous?
Mikel
3
Alt + # fonctionne comme vous le décrivez dans le troisième paragraphe, mais pas comme dans le quatrième. Il ajoute simplement un autre # au début et accepte la ligne. J'utilise bash 4.1.5 (1) -release sur Ubuntu 10.10.
Lauritz V. Thaulow
1
Oh mon Dieu, en bash il faut un argument numérique, par exemple , Esc+1puis Alt+ #pour basculer.
Mikel
Cela fonctionne, mais est beaucoup plus lourd que juste Ctrl + A Suppr Ctrl + E, en particulier sur la disposition de mon clavier où Alt + # est en fait Alt + Shift + 3.
Lauritz V. Thaulow
10

Une de mes fonctionnalités préférées zshest la fonction de ligne de commande intégrée qui s’occupe de cela sans le moindre piratage dans les autres réponses données ici. Je l'ai lié à Ctrl+ ldans mon .zshrcfichier comme ceci:

bindkey '^L' push-line

Ensuite, lorsque je tape quelque commande et que je dois faire autre chose très rapidement, je peux l'invoquer avec une seule touche et obtenir une invite vide. Après avoir exécuté l'autre commande, l'invite est automatiquement renseignée avec ce que je tapais auparavant.

Vous pouvez même enchaîner plusieurs couches et les commandes vous reviendront dans l'ordre inverse de leur insertion dans la file d'attente.

Caleb
la source
5
Relié à Ctrl+Qet ESC qpar défaut (en mode emacs).
Gilles
Y at-il quelque chose de similaire pour bash?
Magnus
@Magnus: S'il vous plaît examiner le reste des réponses à cette question. Il existe des solutions pour Bash, mais pas aussi élégant que cela.
Caleb
@Caleb, j'aurais dû être plus précis, existe-t-il une combinaison similaire à touche unique pour bash?
Magnus
1
C'est clairement la réponse "correcte", pour Zsh en tout cas! Je veux juste mentionner le push-line-or-editwidget, qui n'est lié à aucun keymap par défaut. À l'invite de niveau supérieur, il fait la même chose que push-line, mais à n'importe quel niveau d'invite, il convertit la commande entière entrée en un tampon multi-lignes. Deux fonctions géniales sur une seule touche! Je peux recommander la liaison push-line-or-editau lieu de plaine push-line. Vous ne perdez rien et gagnez des fonctionnalités utiles.
wjv
5

En plus du ctrl- a ctrl- ktruc, si vous êtes à l' écran, juste ctrl- a dà détacher puis rattachez avecscreen -r

Vous pouvez aussi simplement ouvrir une autre fenêtre avec ctrl+a c

garenne
la source
8
Si vous êtes à l'écran, ouvrez une autre fenêtre avec Ctrl+A c.
Gilles
1
@Gilles .. sauf si vous devez utiliser certains aspects de l'état du shell (variables, fonctions, alias, etc.).
Intuition le
4

Une autre manière, pas parfaite cependant, presse Ctrl-X Ctrl-E. Ceci ouvrira votre éditeur par défaut contenant votre commande à moitié tapée. Ensuite, vous pouvez enregistrer votre commande dans un fichier ou ouvrir un nouveau shell à partir de votre éditeur. Lorsque vous quittez le nouveau shell, vous revenez à l'éditeur et l'enregistrement du contenu les exécute automatiquement.

Ce n'est pas parfait car il ne vous renvoie pas à votre shell d'origine, mais force l'exécution de la commande ou la supprime complètement. Mais il n'y a pas de sélections temporaires ou de tampons de neutralisation à craindre, et il y a aussi quelques réglages intéressants, par exemple if editor = vi

:wq            # execute the command
:cq            # cancel and abort
:! command     # execute command
:shell         # open a new shell
:r filename    # insert the contents of a file for editing
:r ! command   # insert the output of a command for editing
forcefsck
la source
Très belle alternative. Je ne suis pas compatible avec emacs, alors je serai heureux comme une palourde de l'utiliser lorsque les outils électriques sont vraiment nécessaires. (En parlant de vi, j'ai récemment essayé l'émulateur linux N64, Mupen64Plus. Esc quitte l'éditeur sans sauvegarder. J'ai vite renoncé à jouer.)
Lauritz V. Thaulow
1
@lazyr, pour debian / ubuntu, lancez sudo update-alternatives --config editoret choisissez votre éditeur préféré. Pour les autres systèmes, définissez les variables d'environnement EDITOR ou VISUAL sur votre éditeur favori, par exemple, ajoutez export EDITOR=/usr/bin/nanovotre .bashrc.
forcefsck
3

Semblable à la méthode d’ajout #en début de ligne, il existe une méthode plus simple que j’utilise qui n’exige pas de revenir au début de la ligne:

Ajoutez simplement un devis ouvert et ne le fermez pas, qu'il soit simple ou double.

Puis appuyez sur Enter.

Puis appuyez sur CtrlC.

La commande partielle est enregistrée dans l'historique des commandes (disponible via la flèche vers le haut) mais n'est pas réellement exécutée.

Wildcard
la source
2

Avec zsh, si vous tapez <ESC> q(échappe, puis Q), votre ligne d’invite sera coupée afin que vous puissiez taper une autre commande. Vous obtiendrez automatiquement votre texte coupé à la prochaine invite.

Il peut se rappeler plusieurs lignes en même temps, vous pouvez donc l'utiliser pendant qu'une ligne vous attend. Vous pouvez même l'utiliser sur une ligne vierge pour retarder la reprise de votre ligne de coupe.

Ce n'est pas le moyen le plus efficace si vous devez utiliser plusieurs commandes pour la vérification / préparation (vous devrez retaper <ESC> qavant chaque commande). Mais je pense qu'il est possible de le lier à un raccourci plus court.


Si vous voulez juste vérifier le manuel, tapez <ESC> h(échappement, puis H). Cela va exécuter le run-helpprédéfini, avec le premier mot de la ligne de commande comme argument. Vous retrouverez votre ligne intacte une fois terminé.

loxaxs
la source
La plupart des terminaux vous laisseront faire M-qau lieu de<ESC> q
sleblanc