Existe-t-il un raccourci pour exécuter une série de commandes dans l'historique bash?

20

Supposons que j'ai l'exemple trivial suivant dans mon history:

...
76 cd ~
77 ./generator.sh out.file
78 cp out.file ~/out/
79 ./out/cleaner.sh .
80 ls -alnh /out
...

Si je voulais exécuter des commandes 77, 78et 79dans une commande, existe-t-il un raccourci pour cela? J'ai essayé !77 !78 !79, qui les placera simplement tous sur une seule ligne à exécuter.

MrDuk
la source
9
Ça !77 ; !78 ; !79va?
thrig
1
Je suppose que tout ce qui est court de taper ligne par ligne est correct, mais j'espérais quelque chose d'un peu plus concis (dans le sens de !77-79)
MrDuk
1
@MrDuk, mon garçon m'a pris du temps pour m'en souvenir. Voir ma réponse mise à jour pour la solution très concise ! :)
Wildcard
C'est magique! :)
MrDuk

Réponses:

28

EDIT: vous pouvez le faire de manière compatible POSIX avec l' outil de commande fixfc :

fc 77 79

Cela ouvrira votre éditeur (probablement vi ) avec les commandes 77 à 79 dans le tampon. Lorsque vous enregistrez et quittez ( :x), les commandes seront exécutées.


Si vous ne souhaitez pas les modifier et que vous êtes TRÈS SÛR de savoir quelles commandes vous appelez, vous pouvez utiliser:

fc -e true 77 79

Cela utilise true comme un "éditeur" pour éditer les commandes avec, il se ferme donc sans apporter de modifications et les commandes sont exécutées telles quelles.


RÉPONSE ORIGINALE:

Vous pouvez utiliser:

history -p \!{77..79} | bash

Cela suppose que vous n'utilisez pas d'alias ou de fonctions ou de variables qui ne sont présentes que dans l'environnement d'exécution actuel, car bien sûr, ils ne seront pas disponibles dans le nouveau shell en cours de démarrage.


Une meilleure solution (merci à Michael Hoffman de me le rappeler dans les commentaires) est:

eval "$(history -p \!{77..79})"

Un des très, très rares cas où cela evalest réellement approprié!


Regarde aussi:

Caractère générique
la source
2
Cela ne fonctionnera pas correctement si l'une des commandes modifie l'environnement d'exécution actuel, par exemple, en changeant une variable ou en faisant un cd, mais c'est un cas de bord.
G-Man dit `` Réintègre Monica ''
3
eval "$(history -p \!{77..79})"devrait marcher.
Michael Hoffman
1
@MichaelHoffman, j'y avais pensé et pensais l'avoir essayé, mais je viens de réaliser que j'ai omis de citer! Oh! Pas étonnant que cela n'ait pas fonctionné ... modification de la réponse maintenant.
Wildcard
14

Réponse simple: au lieu de !77 !78 !79,

  • tapez !77; !78; !79pour faire ce que vous semblez faire - exécutez la commande 77, puis la commande 78, puis la commande 79, sans condition, ou
  • tapez !77 && !78 && !79 pour exécuter la commande 77 et vérifiez si elle a réussi. Et puis, si la commande 77 a réussi, exécutez la commande 78. Et puis, si la commande 78 a réussi, exécutez la commande 79.

Réponse légèrement plus intelligente (si vous êtes dans une fenêtre de type terminal):

  • Déterminez quel numéro de commande sera la prochaine commande que vous tapez.
    • Il est possible de l'inclure dans votre invite; Je crois que c'est en incluant \!dans votre PS1.
    • Ou regardez votre liste d'historique. Si la dernière entrée est 82 history, votre prochaine commande est 83.
  • Soustrayez 83−77 = 6.
  • Tapez !-6. Cela réexécutera la commande 77.
  • Sélectionnez-le !-6, copiez-le et collez-le. Puisque votre réexécution de la commande 77 ( ./generator.sh) était la commande 83, vous êtes maintenant sur la commande 84, donc!-6 exécuterez donc de nouveau la commande 78.
  • Répétez le collage !-6comme vous le souhaitez.
G-Man dit «Réintègre Monica»
la source