# Color Bash Prompt (Русский)

Ссылки по теме

- Bash
- Environment variables

Существуют различные возможности настройки строки приглашения Bash'а (PS1), которые могут сделать работу в командной строке комфортней и продуктивней. Например, можно добавить дополнительную информацию или цвет, чтобы приглашение ввода можно было легко обнаружить среди остального текста.

## Приглашение ввода

Код разметки приглашения ввода содержится в переменной окружения PS1. Обычно его настраивают в конфигурационном файле Bash'а — ~/.bashrc.

Изменить цвет можно с помощью т.н. escape-последовательностей. В общем виде они выглядят так:

    \e[T;Cm или \033[T;Cm или \x1B[T;Cm

где T и C — числа. T задает тип текста (жирный, зачеркнутый и т.д.), а C — его цвет. T можно опустить.

## Список некоторых последовательностей

    Обычный:
    '\e[0;30m' — Черный
    '\e[0;31m' — Красный
    '\e[0;32m' — Зеленый
    '\e[0;33m' — Желтый
    '\e[0;34m' — Синий
    '\e[0;35m' — Фиолетовый
    '\e[0;36m' — Голубой
    '\e[0;37m' — Белый

    Жирный:
    '\e[1;30m' — Черный
    '\e[1;31m' — Красный
    '\e[1;32m' — Зеленый
    '\e[1;33m' — Желтый
    '\e[1;34m' — Синий
    '\e[1;35m' — Фиолетовый
    '\e[1;36m' — Голубой
    '\e[1;37m' — Белый

    Зачеркнутый:
    '\e[4;30m' — Черный
    '\e[4;31m' — Красный
    '\e[4;32m' — Зеленый
    '\e[4;33m' — Желтый
    '\e[4;34m' — Синий
    '\e[4;35m' — Фиолетовый
    '\e[4;36m' — Голубой
    '\e[4;37m' — Белый

    Фон:
    '\e[40m'   — Черный
    '\e[41m'   — Красный
    '\e[42m'   — Зеленый
    '\e[43m'   — Желтый
    '\e[44m'   — Синий
    '\e[45m'   — Фиолетовый
    '\e[46m'   — Голубой
    '\e[47m'   — Белый

    '\e[0m'    — Отмена

## Информационные заполнители

- \u — имя пользователя;
- \h — имя хоста;
- \w — текущий абсолютный путь;
- \W — текущий относительный путь;
- \$ — специальный символ приглашения ('#' — для root'а, '$" — для обычных пользователей).

## Примеры

### Первый

Следующие настройки полезны для визуального различия приглашения root пользователя, от такой же строки обычного пользователя.

- Зелёный цвет для обычного пользователя:

    [chiri@zetsubou ~]$ _

    PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '

- Красный — для root'а:

    [root@zetsubou ~]# _

    PS1='\[\e[1;31m\][\u@\h \W]\$\[\e[0m\] '

### Второй

- Зелено-синее приглашение для обычного пользователя:

    chiri ~/docs $ echo "sample output text"

    sample output text

    chiri ~/docs $ _

    PS1='\[\e[0;32m\]\u\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \[\e[1;32m\]\$\[\e[m\] \[\e[1;37m\]'

Последняя цветовая escape-последовательность, "\[\e[1;37m\]", не закрыта, поэтому следующий за ней текст (то, что вы печатаете в терминале, вывод программ и т.д.) будет окрашен в белый цвет.

- Красно-синее — для root'а:

    root ~/docs # echo "sample output text"

    sample output text

    root ~/docs # _

    PS1='\[\e[0;31m\]\u\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \[\e[0;31m\]\$ \[\e[m\]\[\e[0;32m\]'

## Позиционирование курсора

Эта последовательность устанавливает позицию курсора:

    \[\e[<строка>;<столбец>f\]

Текущая позиция может быть сохранена так:

    \[\e[s\]

Чтобы восстановить позицию, используйте:

    \[\e[u\]

Пример использования последовательностей позиционирования курсора, чтобы отобразить часы в правом верхнем углу:

    PS1=">\[\e[s\]\[\e[1;\$((COLUMNS-4))f\]\$(date +%H:%M)\[\e[u\]"

Переменная окружения COLUMNS содержит число столбцов в терминале. В примере выше из этого значения отнимается 4, чтобы выровнять надпись со временем шириной в 5 символов.

## Список цветов для использования в Bash'е

Вы можете добавить в свой конфиг Bash'а что-то вроде этого:

    red='\e[1;31m'  # Red B
    blue='\e[1;34m' # Blue B
    rst='\e[0m'     # Text reset

и использовать в командной строке:

    $ echo -e "${blue}test"
    test
    $ echo -e "${red}test"
    test
    $ echo -e "${red}red${rst}and${blue}blue"
    red and blue

или в PS1:

    PS1="\[$blue\]foo\[$red\] bar\[$rst\] baz> "

    foo bar baz>

## Advanced prompts

### Load/Mem Status for 256colors

This isn't even pushing the limits.. other than using 'sed' to parse the memory and load average (using the -u option for non-buffering), and the builtin history to save your history to your HISTFILE after every command, which I have found incredibly useful when dealing with crashing shells or subshells, this is essentially just making BASH print variables it already knows, making this extremely fast compared to prompts with non-builtin commands.

This prompt is from AskApache.com's BASH Power Prompt article, which goes into greater detail. It is especially helpful for those wanting to understand 256 color terminals, ncurses, termcap, and terminfo.

This is for 256 color terminals, which is where the \033[38;5;22m terminal escapes come from.

    802/1024MB      1.28 1.20 1.13 3/94 18563
    [5416:17880 0:70] 05:35:50 Wed Apr 21 [srot@host.sqpt.net:/dev/pts/0 +1] ~

    (1:70)$ _

     PROMPT_COMMAND='history -a;echo -en "\033[m\033[38;5;2m"$(( `sed -nu "s/MemFree:[\t ]\+\([0-9]\+\) kB/\1/p" /proc/meminfo`/1024))"\033[38;5;22m/"$((`sed -nu "s/MemTotal:[\t ]\+\([0-9]\+\) kB/\1/Ip" /proc/meminfo`/1024 ))MB"\t\033[m\033[38;5;55m$(< /proc/loadavg)\033[m"'
     PS1='\[\e[m\n\e[1;30m\][$$:$PPID \j:\!\[\e[1;30m\]]\[\e[0;36m\] \T \d \[\e[1;30m\][\[\e[1;34m\]\u@\H\[\e[1;30m\]:\[\e[0;37m\]${SSH_TTY} \[\e[0;32m\]+${SHLVL}\[\e[1;30m\]] \[\e[1;37m\]\w\[\e[0;37m\] \n($SHLVL:\!)\$ '

### Prompt escapes

The various Bash prompt escapes listed in the manpage:

    Bash allows these prompt strings to be customized by inserting a
    number of backslash-escaped special characters that are
    decoded as follows:

      \a         an ASCII bell character (07)
      \d         the date in "Weekday Month Date" format (e.g., "Tue May 26")
      \D{format} the format is passed to strftime(3) and the result
                 is inserted into the prompt string an empty format
                 results in a locale-specific time representation.
                 The braces are required
      \e         an ASCII escape character (033)
      \h         the hostname up to the first `.'
      \H         the hostname
      \j         the number of jobs currently managed by the shell
      \l         the basename of the shell's terminal device name
      \n         newline
      \r         carriage return
      \s         the name of the shell, the basename of $0 (the portion following
                 the final slash)
      \t         the current time in 24-hour HH:MM:SS format
      \T         the current time in 12-hour HH:MM:SS format
      \@         the current time in 12-hour am/pm format
      \A         the current time in 24-hour HH:MM format
      \u         the username of the current user
      \v         the version of bash (e.g., 2.00)
      \V         the release of bash, version + patch level (e.g., 2.00.0)
      \w         the current working directory, with $HOME abbreviated with a tilde
      \W         the basename of the current working directory, with $HOME
                 abbreviated with a tilde
      \!         the history number of this command
      \#         the command number of this command
      \$         if the effective UID is 0, a #, otherwise a $
      \nnn       the character corresponding to the octal number nnn
      \\         a backslash
      \[         begin a sequence of non-printing characters, which could be used
                 to embed a terminal control sequence into the prompt
      \]         end a sequence of non-printing characters

      The command number and the history number are usually different:
      the history number of a command is its position in the history
      list, which may include commands restored from the history file
      (see HISTORY below), while the command number is the position in
      the sequence of commands executed during the current shell session.
      After the string is decoded, it is expanded via parameter
      expansion, command substitution, arithmetic expansion, and quote
      removal, subject to the value of the promptvars shell option (see
      the description of the shopt command under SHELL BUILTIN COMMANDS
      below).

## Отображения кода, возвращенного командой

Добавьте это в ваш конфиг Bash'а, чтобы всегда видеть, какой код вернула последняя команда:

     PROMPT_COMMAND='RET=$?; if [[ $RET -eq 0 ]]; then echo -ne "\e[32m$RET\e[0m ;)"; else echo -ne "\e[31m$RET\e[0m ;("; fi; echo -n " "'

Выглядит примерно так:

    0 ;) harvie@harvie-ntb ~/ $ true
    0 ;) harvie@harvie-ntb ~/ $ false
    1 ;( harvie@harvie-ntb ~/ $

Нуль — зеленый, не нуль — красный.

Если подсветка не нужна, просто используйте $?. Эта переменная хранит код, вовращенный последней командой.

## Wolfman's

After reading through most of the Bash Prompt Howto, the author developed a color bash prompt that displays the last 25 characters of the current working directory. This prompt should work well on terminals with a black background. The following code goes in file `~/.bashrc`.

- Add the bash_prompt_command function. If you have a couple directories with long names or start entering a lot of subdirectories, this function will keep the command prompt from wrapping around the screen by displaying at most the last pwdmaxlen characters from the PWD. This code was taken from the Bash Prompt Howto's section on Controlling the Size and Appearance of $PWD and modified to replace the user's home directory with a tilde.

    ##################################################
    # Fancy PWD display function
    ##################################################
    # The home directory (HOME) is replaced with a ~
    # The last pwdmaxlen characters of the PWD are displayed
    # Leading partial directory names are striped off
    # /home/me/stuff          -> ~/stuff               if USER=me
    # /usr/share/big_dir_name -> ../share/big_dir_name if pwdmaxlen=20
    ##################################################
    bash_prompt_command() {
        # How many characters of the $PWD should be kept
        local pwdmaxlen=25
        # Indicate that there has been dir truncation
        local trunc_symbol=".."
        local dir=${PWD##*/}
        pwdmaxlen=$(( ( pwdmaxlen < ${#dir} ) ? ${#dir} : pwdmaxlen ))
        NEW_PWD=${PWD/#$HOME/\~}
        local pwdoffset=$(( ${#NEW_PWD} - pwdmaxlen ))
        if [ ${pwdoffset} -gt "0" ]
        then
            NEW_PWD=${NEW_PWD:$pwdoffset:$pwdmaxlen}
            NEW_PWD=${trunc_symbol}/${NEW_PWD#*/}
        fi
    }

- The next fragment generates the command prompt and various colors are defined. The user's color for the username, hostname, and prompt ($ or #) is set to cyan, and if the user is root (root's UID is always 0), set the color to red. The command prompt is set to a colored version of Arch's default with the NEW_PWD from the last function.

  Also, make sure that your color variables are enclosed in double and not single quote marks. Using single quote marks seems to give Bash problems with line wrapping correctly.

    bash_prompt() {
        case $TERM in
         xterm*|rxvt*)
             local TITLEBAR='\[\033]0;\u:${NEW_PWD}\007\]'
              ;;
         *)
             local TITLEBAR=""
              ;;
        esac
        local NONE="\[\033[0m\]"    # unsets color to term's fg color

        # regular colors
        local K="\[\033[0;30m\]"    # black
        local R="\[\033[0;31m\]"    # red
        local G="\[\033[0;32m\]"    # green
        local Y="\[\033[0;33m\]"    # yellow
        local B="\[\033[0;34m\]"    # blue
        local M="\[\033[0;35m\]"    # magenta
        local C="\[\033[0;36m\]"    # cyan
        local W="\[\033[0;37m\]"    # white

        # emphasized (bolded) colors
        local EMK="\[\033[1;30m\]"
        local EMR="\[\033[1;31m\]"
        local EMG="\[\033[1;32m\]"
        local EMY="\[\033[1;33m\]"
        local EMB="\[\033[1;34m\]"
        local EMM="\[\033[1;35m\]"
        local EMC="\[\033[1;36m\]"
        local EMW="\[\033[1;37m\]"

        # background colors
        local BGK="\[\033[40m\]"
        local BGR="\[\033[41m\]"
        local BGG="\[\033[42m\]"
        local BGY="\[\033[43m\]"
        local BGB="\[\033[44m\]"
        local BGM="\[\033[45m\]"
        local BGC="\[\033[46m\]"
        local BGW="\[\033[47m\]"

        local UC=$W                 # user's color
        [ $UID -eq "0" ] && UC=$R   # root's color

        PS1="$TITLEBAR ${EMK}[${UC}\u${EMK}@${UC}\h ${EMB}\${NEW_PWD}${EMK}]${UC}\\$ ${NONE}"
        # without colors: PS1="[\u@\h \${NEW_PWD}]\\$ "
        # extra backslash in front of \$ to make bash colorize the prompt
    }

- Finally, append this code. This ensures that the NEW_PWD variable will be updated when you cd somewhere else, and it sets the PS1 variable, which contains the command prompt.

    PROMPT_COMMAND=bash_prompt_command
    bash_prompt
    unset bash_prompt

## KitchM's

These prompts offer a little more flash and visual clarity. Note that the use of red in the root user's prompt should provide ample warning. That's not to say someone couldn't use flashing text or arrow to do even more, but these will give you a good starting point.

First, change the default background in your terminal preferences (this example uses Xfce's Terminal program) to #D2D2D2, and the text color to #000000. The font is listed as DejaVu Sans Mono Book 12. The cursor color is #00AA00, and the tab activity color is #AF0000.

Second, in ~/.bashrc and right after the PS1= line, enter a new line with the following:

    PS1='\e[1;33;47m\u \e[1;32;47mon \h \e[1;35;47m\d \@\e[0;0m\n\e[1;34m[dir.= \w] \# > \e[0;0m'

And then place a # in front of the first PS1 line to remark it out.

Third, for root user, edit /root/.bashrc in the same manner to include:

    PS1='\e[1;31;47m\u \e[1;32;47mon \h \e[1;35;47m\d \@\e[0;0m\n\e[1;31m[dir.= \w] \# > \e[0;0m'

Don't forget to comment out the old line.

These are double-line prompts, and they should look something like these:

User-

    Username on myhost Sun Jan 15 12:30 PM
    [dir.= /home/username] 1 >

Root-

    Root on myhost  Sun Jan 15 12:30 PM
    [dir.= /etc/rc.d] 1 >

You'll note that the background colors make them easier to read, and the text colors just keep things interesting. There's a lot of leeway to make them personalized, just with the use of colors. Enjoy!

## Different colors for text entry and console output

If you don't reset the text color at the end of your prompt, both the text you enter and the console text will simply stay in that color. If you want to edit text in a special color but still use the default color for command output, you'll need to reset the color after you press enter, but still before any commands get run. To do this, install a DEBUG trap in your ~/.bashrc like this:

    trap 'echo -ne "\e[0m" > $(tty)' DEBUG

And add yourself to the tty group:

    sudo gpasswd -add <username> tty

Now bash will execute the DEBUG trap every time before running a command. We have to echo the reset sequence directly to the terminal device (as reported by tty), otherwise the sequence would become part of the command output (and thus part of any redirected data). To be able to write to the terminal device we need to be part of the tty group.

This is a bit of a hack, so use it at your own risk.

## Внешние ссылки

- Форум:
  - BASH prompt
  - What's your PS1?
- http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
- Giles Orr's collection of sample prompts
- Годный PS1-генератор

Categories:

- Русский
- Command shells (Русский)