web-dev-qa-db-fra.com

Comment puis-je diriger chaque commande donnée au shell?

Je voudrais éditer mon .bashrc afin que chaque commande exécutée sur le shell soit dirigée vers quelque chose, par exemple:

 $ Sudo apt update
  _________________
< Sudo apt update >
 -----------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

J'ai réussi quelque chose d'assez similaire, mais pas tout à fait:

$ bash
$ exec > >(cowsay)
$ echo "Hello AU!"
$ exit
 _______
< Hello AU! >
 -------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

Ce n'est pas le résultat souhaité, car cela ne se produit qu'après la sortie du Shell actuel.

C'est principalement pour s'amuser/apprendre.

13
M. Becerra

Vous pouvez adapter votre méthode un peu. Au lieu de rediriger directement vers cowsayname__, lisez la sortie jusqu'à un caractère de délimitation, envoyez cette sortie à cowsayname__, puis imprimez ce caractère après chaque commande:

exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
Prompt_COMMAND='printf "\0"'

Ici, j'utilise le caractère ASCII NUL. Vous pouvez utiliser quelque chose d'autre qui ne risque pas d'apparaître dans la sortie de la commande.

Cela s’imprimera après l’invite, le résultat sera donc moche:

$ export LC_ALL=C
$ exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
$ Prompt_COMMAND='printf "\0"'
$ ls
$
 ______________________________________
/ Desktop Documents Downloads Music    \
| Pictures Public Templates Videos
\ examples.desktop                     /
 --------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ echo foo
$
 ______
< foo  >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Notez que cela interrompt toute commande qui tente une sortie complexe ou possède une interface utilisateur texte (pensez aux éditeurs de ligne de commande, pagers, etc.).

En supposant que vous sachiez déjà ce que exec > >(...) fait, la partie de la substitution de processus est la suivante:

  • while IFS= read -d '' -r line; do ... done: il s'agit d'un langage assez courant pour la lecture de données délimitées par le caractère ASCII NUL:

    • IFS= définit l'IFS sur la chaîne vide, ce qui désactive le fractionnement des champs
    • -r empêche readde traiter spécialement \ dans l'entrée (ainsi, \n par exemple, est lu en tant que \n et n'est pas converti en caractère de nouvelle ligne).
    • -d '' est le moyen de demander à readde lire jusqu'au caractère NUL

    Ainsi, tout se répète sur l'entrée dans les sections délimitées par NUL, tout en préservant le plus possible le contenu de l'entrée.

  • if [[ -n $line ]]; then ... fi; done - n'agit que si l'entrée lue jusqu'à présent n'est pas vide.
  • echo; printf "%s\n" "$line" | cowsay; - affiche une ligne vide principale pour que la sortie de cowsay ne soit pas en conflit avec l'invite, puis envoie l'entrée lue jusqu'à présent à cowsay. printfest plus fiable et plus sûr que echoname__.
12
muru

Vous pouvez trap et abuser du signal DEBUG de bash:

trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG

Exemple d'exécution

$ trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
AU is awesome!

Cependant, cela exécutera toujours la commande après. Grâce à ilkkach j'ai trouvé un moyen de contourner cela:

$ shopt -s extdebug
$ trap 'bash -c "$BASH_COMMAND" | cowsay; false' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
16
dessert