Tips to Customize Command Line Prompt in Linux

The command line prompt in Linux could be customized to user’s need. It is achieved by modifying a series of environment variables, such as PS1, PROMPT_COMMAND and PS2.

Prompting

Bash has already defined a series of prompt variables. They are list in a page of bash manual here. Several variables that I used are listed as follows:

  • \u - The username of the current user;
  • \h - The hostname, up to the first ‘.’;
  • \w - The current working directory, with $HOME abbreviated with a tilde (uses the $PROMPT_DIRTRIM variable);
  • \t - The time, in 24-hour HH:MM:SS format;

The way to use those prompt variables is simply including them in PS1, or other prompt related environment variables, as escape characters. For example:

PS1='\u@\h:\w \$'

They would be expanded before bash prints each prompt.

PROMPT_COMMAND

The value of the variable PROMPT_COMMAND is examined just before Bash prints each primary prompt. If PROMPT_COMMAND is set and has a non-null value, then the value is executed just as if it had been typed on the command line.

With the help of PROMPT_COMMAND, it is much more flexible for user to composite their own string of prompt. User could create a series of temporary variables in PROMPT_COMMAND, then use those temperary variables as pre-defined prompt variables. Here comes an example:

PROMPT_COMMAND='PWDHEAD=${PWD:0:5}; PWDTAIL=${PWD: -8}; PWDTAIL=${PWDTAIL:-$PWD}'
PS1='\u@\h: $PWDHEAD...$PWDTAIL %'

Three formats of trimming are used in the above example:

${parameter:offset}
${parameter:offset:length}

Expands to up to length characters of parameter starting at the character specified by offset. If length is omitted, expands to the substring of parameter starting at the character specified by offset. […] If offset evaluates to a number less then zero, the value is used as an offset from the end of the value of parameter.

${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is subsituted.

The prompt then would look like:

bambo@BW-E431: /home...me/bambo %

Here comes a more complicated and fancy example:

PROMPT_COMMAND='PS1X=$(p="${PWD#$HOME}"; [ "${PWD}" != "${p}" ] && printf "~" && p="/${p}"; IFS=/; for q in ${p:1}; do printf /${q:0:1}; done; printf "${q:1})'
PS1='\u@\h:${PS1X} %'

This example PROMPT_COMMAND prepares a variable PS1X for PS1 to use. It substitute $HOME in $PWD with tilde first, then traverses through the string to pick out the first letter for every level directory, only the last level’s directory name gets completed finally.

The prompt then would look like this:

bambo@BW-E431:~/A/l/l/s/b/d/hdl %

Supplemental Helpful Tips

PS1 is most frequently used. While PS2 is used in other situation, when we break a long command to several lines in the command line using \, the PS2 would appear in the front of following lines.

Above customizations work with environment variable, so of course you can try them out in command line. To keep the customizations, modify file ~/.bashrc or ~/.profile, and export those environment variables in that files.

Somehow the string assigned to PS1 needs to be in strong quoting, which uses single-quotes instead of double-quotes, otherwise its variables would not be expanded.

Credits