PROMPT_COMMAND peut contenir des instructions bash ordinaires tandis que la variable PS1 peut également contenir des caractères spéciaux, tels que «\ h» pour le nom d'hôte, dans la variable.
Par exemple, voici mon invite bash qui utilise à la fois PROMPT_COMMAND et PS1. Le code bash dans PROMPT_COMMAND détermine dans quelle branche git vous pourriez être et l'affiche à l'invite, ainsi que l'état de sortie du dernier processus exécuté, le nom d'hôte et le nom de base du pwd. La variable RET stocke la valeur de retour du dernier programme exécuté. Ceci est pratique pour voir s'il y a eu une erreur et le code d'erreur du dernier programme que j'ai exécuté dans le terminal. Notez le «externe» entourant toute l'expression PROMPT_COMMAND. Il inclut PS1 afin que cette variable soit réévaluée à chaque fois que la variable PROMPT_COMMAND est évaluée.
PROMPT_COMMAND='RET=$?;\
BRANCH="";\
ERRMSG="";\
if [[ $RET != 0 ]]; then\
ERRMSG=" $RET";\
fi;\
if git branch &>/dev/null; then\
BRANCH=$(git branch 2>/dev/null | grep \* | cut -d " " -f 2);\
fi;
PS1="$GREEN\u@\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";'
L'exemple de sortie ressemble à ceci dans un répertoire non-git:
sashan@dhcp-au-122 Documents $ false
sashan@dhcp-au-122 Documents 1 $
et dans un répertoire git, vous voyez le nom de la branche:
sashan@dhcp-au-122 rework mybranch $
Mettre à jour
Après avoir lu les commentaires et la réponse de Bob, je pense qu'il est préférable de l'écrire comme il le décrit. C'est plus facile à maintenir que ce que j'ai écrit à l'origine ci-dessus, où la variable PS1 est définie dans PROMPT_COMMAND, qui est elle-même une chaîne super compliquée qui est évaluée au moment de l'exécution par bash. Cela fonctionne, mais c'est plus compliqué que nécessaire. Pour être honnête, j'ai écrit ce PROMPT_COMMAND pour moi-même il y a environ 10 ans et cela a fonctionné et n'y a pas trop pensé.
Pour ceux qui sont curieux de savoir comment j'ai modifié mes choses, j'ai essentiellement mis le code de PROMPT_COMMAND dans un fichier séparé (comme Bob l'a décrit), puis j'ai fait écho à la chaîne que j'ai l'intention d'être PS1:
GREEN="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour
if [ -z $SCHROOT_CHROOT_NAME ]; then
SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
if [[ $RET != 0 ]]; then
ERRMSG=" $RET"
fi
if which git &>/dev/null; then
BRANCH=$(git branch 2>/dev/null | grep \* | cut -d " " -f 2)
else
BRANCH="(git not installed)"
fi
echo "${GREEN}\u@\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} \$ $RESTORE"
et dans mon .bashrc
function prompt_command {
RET=$?
export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command
if git branch &>/dev/null ; then\
. Il redirige à la fois stdout et stderr vers / dev / null. tldp.org/LDP/abs/html/io-redirection.htmlPROMPT_COMMAND
.Don't set PS1 in PROMPT_COMMAND! Set variables in PROMPT_COMMAND and use them in PS1
PS1
ligne à l'intérieurPROMPT_COMMAND
est désavantageux. C'est un code utile parfait. Contrairement à la réponse de Bob vers le bas, laPS1
variable a été correctement construite. Cela permet une invite de bash beaucoup plus sophistiquée en fonction de votre situation réelle.PS1
intérieur de @ChristianWolfPROMPT_COMMAND
ne sert à rien. c'est un exemple de comment ne pas le faire. construisezPS1
une fois dedans.bash_profile
, utilisez simplement des guillemets simples au lieu de guillemets doubles, de sorte que les substitutions de variables seront évaluées à chaque invite.La différence est que PS1 est la chaîne d'invite réelle utilisée et PROMPT_COMMAND est une commande qui est exécutée juste avant l'invite. Si vous voulez la manière la plus simple et la plus flexible de créer une invite, essayez ceci:
Mettez ceci dans votre .bashrc:
Ensuite, écrivez un script (bash, perl, ruby: votre choix), et placez-le dans ~ / bin / bash_prompt.
Le script peut utiliser n'importe quelle information pour créer une invite. C'est beaucoup plus simple IMO car vous n'avez pas à apprendre le langage de substitution un peu baroque qui a été développé uniquement pour la variable PS1.
Vous pourriez penser que vous pourriez faire de même en définissant simplement PROMPT_COMMAND directement sur ~ / bin / bash_prompt, et en définissant PS1 sur la chaîne vide. Au début, cela semble fonctionner, mais vous découvrez rapidement que le code readline s'attend à ce que PS1 soit défini sur l'invite réelle, et lorsque vous faites défiler les backwords dans l'historique, les choses se gâtent en conséquence. Cette solution de contournement oblige PS1 à toujours refléter la dernière invite (puisque la fonction définit la PS1 réelle utilisée par l'instance appelante du shell), ce qui permet à readline et à l'historique des commandes de fonctionner correctement.
la source
PS1
enPROMPT_COMMAND
! Définissez des variables dansPROMPT_COMMAND
et utilisez-les dansPS1
. Sinon, vous perdrez la possibilité d'utiliser lesPS1
séquences d'échappement comme\u
ou\h
. Vous devez les réinventerPROMPT_COMMAND
. Cela pourrait être possible, mais il n'est pas possible de contourner la perte de\[
et\]
qui marquent le début et la fin des caractères non imprimables. Cela signifie que vous ne pouvez pas utiliser de couleurs sans confondre le terminal sur la longueur de l'invite. Et cela crée de la confusionreadline
lors de la modification d'une commande engendrant deux lignes. En fin de compte, vous avez un gros désordre sur l'écran.PROMPT_COMMAND
est exécuté avant l'impressionPS1
. Je ne vois aucun problème de réglagePS1
de l'intérieurPROMPT_COMMAND
, car une foisPROMPT_COMMAND
terminé, le shell imprimeraPS1
, qui a été modifié à partir dePROMPT_COMMAND
(ou dans ce cas, à l'intérieurprompt_command
)?export PS1='$(~/bin/bash_prompt)'
fait la même chose que le bogue semble sainDe
man bash
:Si vous souhaitez simplement définir la chaîne d'invite, l'utilisation
PS1
seule suffit:Si vous voulez faire autre chose juste avant d'imprimer l'invite, utilisez
PROMPT_COMMAND
. Par exemple, si vous souhaitez synchroniser les écritures mises en cache sur le disque, vous pouvez écrire:la source
PS1
sans avoir besoinPROMPT_COMMAND
, car la séquence qui définit le titre peut être incluse dansPS1
enveloppé avec\[
et\]
.PS1
, elle sera simplement définie dans le sous-shell, vous ne pouvez donc pas récupérer sa valeur. mais votre exemple est trivialPS1='$(sync)user \u on host \h$ '
la différence est que
PROMPT_COMMAND
, votre invite bash sera visséePS1
substituts\H
et amisPROMPT_COMMAND
exécute son contenu,PS1
utilise son contenu comme invite.PS1
fait l'expansion de variable et la substitution de commande à chaque invite, pas besoin d'utiliserPROMPT_COMMAND
pour attribuer une valeurPS1
ou pour exécuter du code arbitraire. vous pouvez facilement le faireexport PS1='$(uuidgen) $RANDOM'
une fois.bash_profile
, utilisez simplement des guillemets simplesla source
Ouais, alors pour essayer de vraiment comprendre ça:
PROMPT_COMMAND
est une variable / fonction pratique de bash , mais il n'y a, à proprement parler, rien qui ne puisse être fait en utilisantPS1
seul, n'est-ce pas ?Je veux dire, si l'on veut définir une autre variable avec une portée en dehors de l'invite: selon le shell, cette variable devrait probablement être déclarée en premier à l'extérieur
$PS1
ou (dans le pire des cas), on pourrait avoir envie de quelque chose en attente sur un FIFO avant appel$PS1
(et armé à nouveau à la fin de$PS1
); cela\u
\h
pourrait causer des problèmes, en particulier si vous utilisez une expression régulière sophistiquée; mais sinon: on peut accomplir tout ce que l'PROMPT_COMMAND
on peut en utilisant la substitution de commandes à l'intérieur$PS1
(et, peut-être dans les cas de coin, des sous-shell explicites)?Droite?
la source