Comment annuler les modifications dans l'historique des commandes?

12

Dans les systèmes UNIX, vous pouvez appuyer sur les flèches haut et bas pour parcourir les commandes précédentes. C'est extrêmement pratique.

Parfois, je monte et trouve une commande que je veux réutiliser, mais avec quelques variantes. Si j'effectue de telles modifications, je n'ai aucun moyen de récupérer la commande d'origine, sauf si je l'enregistre history.

Existe-t-il un moyen d'annuler les modifications de la commande dans l'historique accessible via les touches?

Ma solution de contournement actuelle consiste à ajouter un préfixe #à la commande. De cette façon, la commande actuelle est exécutée en tant que commentaire, donc rien ne se passe. Ensuite, je peux à nouveau parcourir les commandes avec les touches. Le problème est que la commande que j'utilisais peut être très éloignée de la liste, donc remonter 200 fois c'est un peu. Control + R n'est pas non plus une solution, car je ne me souviens peut-être pas exactement de ce que je cherchais.

Exemple

J'ai tapé "il y a 50 commandes":

ls -l /etc/httpd/conf/

Maintenant, je suis allé jusqu'à cette ligne et l'ai changé en

ls -l /etc/init.d/

mais n'a pas appuyé sur Entrée. Maintenant, je veux revenir au ls -l /etc/httpd/conf/.

Mon environnement

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm
fedorqui
la source
La modification de l'historique des commandes est probablement une (mauvaise) caractéristique du shell que vous utilisez. Dans ksh, par exemple, vous pouvez modifier les entrées d'historique et les appeler sans supprimer la "version précédente" de l'entrée; vous avez toutes les commandes appelées disponibles.
Janis
Avec "ça change", je veux dire que: étant donné une commande précédente que j'ai changé après l'avoir atteinte avec les flèches, si je monte et descend avec les flèches, l'ancienne commande ne montrera pas comment c'était, mais la façon dont j'ai modifié il. Bien sûr, si je tape "enter" en exécutant une commande, cette ancienne commande sera telle qu'elle était initialement; mais c'est précisément ce que j'essaye d'éviter et cherche un moyen de "réinitialiser" la commande à sa valeur initiale.
fedorqui
1
Dans ce cas également, kshle comportement de diffère ici, semble-t-il. Et vos options de modification d'historique dépendent également du mode d'édition choisi. Dans kshle vi-mode de, par exemple, l'ancienne entrée n'est pas écrasée, et je peux également émettre une commande d'annulation, comme dans vi, avec 'u'.
Janis
Uhms, cela semble très prometteur. Je travaille maintenant à Bash et je n'envisage pas actuellement de changer pour ksh, mais il est bon de savoir qu'une telle chose existe là-bas.
fedorqui
Je voudrais savoir où bash stocke l'historique des commandes récentes avant d'écrire dans le fichier historique lorsque le shell est fermé. Cela peut aider à déterminer si cela est possible. N'importe qui? Je pensais que cela pourrait être dans l'une des variables du shell, mais je n'ai pas le temps de parcourir le manuel pour le moment.
iyrin

Réponses:

10

Tant que vous avez modifié une entrée d'historique mais que vous n'avez pas Enterencore appuyé , pour revenir à l'entrée d'origine, appuyez plusieurs fois sur Ctrl+ _- la undocommande - jusqu'à ce qu'elle ne fasse plus de changement. Vous revenez à l'entrée d'origine.

Gilles 'SO- arrête d'être méchant'
la source
5

Revenez à la commande d'origine lorsque vous avez apporté plusieurs modifications à la ligne:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

Mest la méta clé, qui est altrpour moi.


Informations gratuites mais utiles

Lorsque vous avez exécuté une commande comme OP l'avait fait précédemment (cela arrive), il n'y a rien à "annuler" car les commandes sont gérées et mémorisées par la bibliothèque GNU Readline et ne$HISTFILE sont écrites que lorsque le shell se termine. La raison pour laquelle je mentionne cela parce que vous ne pouvez pas grepl' $HISTFILEcomme on pouvait s'y attendre et il ne peut pas être idéal pour sortir de la coquille.

Voici donc quelques options pour vous éviter de faire défiler toutes les commandes de lecture précédentes.

Si vous vous souvenez d'une partie de la commande , appuyez sur ctrl+ ret tapez ce dont vous vous souvenez pour rechercher dans les commandes précédentes contenant cette chaîne. Appuyez à nouveau sur ctrl+ rpour afficher le suivant le plus récent, en effectuant une recherche vers l'arrière.

Par exemple, tapez ls -lpuis ctrl+ rautant de fois qu'il le faut pour trouver la commande précédente que vous recherchez. Si vous le faites défiler, ctrl+ srecherchera vers l'avant à partir de la position actuelle.

La fccommande bash intégrée est utile pour répertorier les numéros d'index aux côtés des commandes readline précédentes.

fc -l -100 listera les 100 commandes précédentes en ligne de lecture.

De plus, si OP sait qu'il recherche une ls -lcommande précédente , il peut diriger la sortie vers greppar exemple:fc -l -100 | grep 'ls -l'

Cela devrait produire une liste des ls -lcommandes précédentes précédées d'un numéro d'index. La sortie ressemble à ceci:
2065 ls -l

Vous pouvez maintenant utiliser l'indicateur d' événement !nnest le numéro d'index. Dans cet exemple, l'exécution !2065s'étendra à ls -l.


Bien que cela n'aide pas après coup, quiconque cherche à conserver l'historique des commandes récentes lors de la modification des commandes précédentes devrait voir la HISTORY EXPANSIONsection de man bash. Voici quelques méthodes alternatives pour modifier les anciennes commandes sans écraser l'historique.

La Event Designatorssection montre comment vous pouvez facilement modifier la chaîne à partir de la dernière commande utilisée.

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

Exemple:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

Les commandes les plus récentes afficheront désormais:

echo foo
echo bar

L'exemple ci-dessus explique également comment utiliser sedpour remplacer une chaîne dans un désignateur d'événement.

!-n    Refer to the current command minus n.

Donc, si 3 commandes apparaissent dans l'historique, echo foovous utiliserez:
!-3:s/foo/bar

Notez que les désignateurs d'événements apparaîtront dans votre historique lors de l'exécution de la commande, dans ce cas echo bar. Il n'apparaîtra pas dans l'historique comme !-3:s/foo/bar.

Il suffit de jeter cela là-bas car cela semble étroitement lié, même s'il s'agit plus d'un "ne pas faire" que la solution "annuler" qu'OP recherche.

iyrin
la source
C'est sympa, merci beaucoup pour les informations détaillées. J'accepte la réponse de Gilles car elle fait exactement ce que je recherche, alors qu'ici vous supposez que je connais beaucoup de choses sur la commande que je veux refaire, ce qui n'est pas toujours le cas.
fedorqui
Oui je suis d'accord. Ce serait formidable si cette fonction d'annulation était étendue à des commandes que j'avais entrées précédemment.
iyrin