Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
612 views
in Technique[技术] by (71.8m points)

bash - What is the difference between PS1 and PROMPT_COMMAND?

While taking a look at this awesome thread I noticed that some examples use

PS1="Blah Blah Blah"

and some use

PROMPT_COMMAND="Blah Blah Blah"

(and some use both) when setting the prompt in a Bash shell. What is the difference between the two? A Stack?Overflow search and even a bit of broader Google searching aren't getting me results, so even a link to the right place to look for the answer would be appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

PROMPT_COMMAND can contain ordinary Bash statements whereas the PS1 variable can also contain the special characters, such as 'h' for hostname, in the variable.

For example, here is my Bash prompt that uses both PROMPT_COMMAND and PS1. The Bash code in PROMPT_COMMAND works out what Git branch you might be in and displays that at the prompt, along with the exit status of the last run process, hostname and basename of the pwd.

The variable RET stores the return value of the last executed program. This is convenient to see if there was an error and the error code of the last program I ran in the terminal. Note the outer ' surrounding the entire PROMPT_COMMAND expression. It includes PS1 so that this variable is reevaluated each time the PROMPT_COMMAND variable is evaluated.

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="$GREENu@h $BLUEW $CYAN$BRANCH$RED$ERRMSG $ $LIGHT_GRAY";'

Example output looks like this in a non-Git directory:

sashan@dhcp-au-122 Documents  $ false
sashan@dhcp-au-122 Documents  1 $

And in a Git directory you see the branch name:

sashan@dhcp-au-122 rework mybranch $

Update

After reading the comments and Bob's answer, I think that writing it as he describes is better. It's more maintainable than what I originally wrote above, where the PS1 variable is set inside the PROMPT_COMMAND, which itself is a super complicated string that is evaluated at runtime by Bash.

It works, but it's more complicated than it needs to be. To be fair, I wrote that PROMPT_COMMAND for myself about 10 years ago and it worked and didn't think too much about it.

For those curious as to how I've amended my things, I've basically put the code for the PROMPT_COMMAND in a separate file (as Bob described) and then echo the string that I intend to be PS1:

GREEN="[33[0;32m]"
CYAN="[33[0;36m]"
RED="[33[0;31m]"
PURPLE="[33[0;35m]"
BROWN="[33[0;33m]"
LIGHT_GRAY="[33[0;37m]"
LIGHT_BLUE="[33[1;34m]"
LIGHT_GREEN="[33[1;32m]"
LIGHT_CYAN="[33[1;36m]"
LIGHT_RED="[33[1;31m]"
LIGHT_PURPLE="[33[1;35m]"
YELLOW="[33[1;33m]"
WHITE="[33[1;37m]"
RESTORE="[33[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"

And in my .bashrc file:

function prompt_command {
    RET=$?
    export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...