LoginSignup
39
36

More than 5 years have passed since last update.

Ubuntuのデフォルト設定から学ぶbashプロンプト

Last updated at Posted at 2016-07-29

ターミナルに表示される user@host:~$ みたいなものは変数 PS1 で設定できると習ったのだが、Ubuntuのデフォルトの設定を見てみるとやけに複雑な形をしていて、何を表しているのかさっぱり分からなかった。

user@host:~$ echo "'$PS1'"
'\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

なので、これを理解するために調べたことをまとめておく。

使用した環境は以下の通り。

  • Ubuntu 14.04
  • bash 4.3.11
  • GNOME端末 3.6.2 (TERM=xterm)
  • (色がつくようにだけ設定変更あり)

.bashrcの内容

パラメーターによる条件分岐や参考になるコメントが書いてあるので、プロンプト設定に関わる部分を抜粋する。なお force_color_prompt=yes のコメントアウトは外してある。

~/.bashrc
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    # We have color support; assume it's compliant with Ecma-48
    # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
    # a case would tend to support setf rather than setaf.)
    color_prompt=yes
    else
    color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

記号の意味

プロンプト用の特殊な文字列

バックスラッシュで始まる特定の文字列は、プロンプトに用いると別の文字列に変換される。

  • \u : ユーザー名
  • \h : ホスト名
  • \w : 現在のディレクトリ(フルパス)
  • \$ : ふつうは $、実効uidが0なら #
  • \[...\] : 表示しない文字列(ターミナル制御用のもの)はこれで囲っておくこと1
  • \033, \e : エスケープ文字
  • \a : ベル文字

他にもたくさんある。一覧はネットでも man bash でも調べられるので省略。

変数展開

$変数名 または ${変数名} と書いてあると、変数の表す文字列に展開される。シェルコマンドやスクリプトの中で使うことが多いが、プロンプトを表示する際にも展開が有効。そのため、変数を定義したら PS1 を再設定しなくても次行のプロンプトにすぐ反映される。

変数をただ展開するだけでなく、変数の状態に応じて処理を変えることもできる。${変数名:+文字列} は、「変数の値が存在していたら指定の文字列に展開」となる。今回の ${debian_chroot:+($debian_chroot)} の場合は、例えば debian_chroot=foobar と定義されていれば文字列 (foobar) に展開する(つまり丸括弧で囲んで出力)。未定義または空文字列なら何も表示されない。

user@host:~$ debian_chroot="foobar"
(foobar)user@host:~$ debian_chroot=""
user@host:~$ unset debian_chroot
user@host:~$ 

プロンプトで展開するためには、PS1 を定義する際には展開しないようにする必要がある。そのためには、PS1='$var' と文字列をシングルクォートで括るか、PS1="\$var" とエスケープすればいい。(PS1='\$var' だとバックスラッシュが残って前節の \$ の意味になるのでダメ)

debian_chroot

肝心のこの変数の利用法については、参考に挙げたページの説明が分かりやすかった。

.bashrc にもある通り、 debian_chroot には /etc/debian_chroot の内容を(可能なら)セットしている。この仕組みが役立つのは、chroot コマンドでルートディレクトリを変えるとき。あるサブディレクトリに別のLinux環境が一式入っている場合、ルートディレクトリをそこへ切り替えれば、全てのパスの指し示す先がサブディレクトリ以下となるため、そのまま別のLinuxを使用する状態にできる。各環境内にあらかじめ /etc/debian_chroot を用意しておけば、どの環境を使用中かプロンプトから区別することができる。

ASCII制御文字

\e (\033), \a (\007) はプロンプトの中で制御文字 ESC, BEL に変換される。これら自体はまともな文字として表示されないが、決められた一連の文字列を作るとターミナルが特別な動作をする。

文字の装飾

\033[...m のようになっているところでは色や太字などの制御をしている。使われている番号の意味は以下の通り。

  • 0 : 全部リセット
  • 1 : 太字
  • 32 : 文字色を緑
  • 34 : 文字色を青

0番台では太字以外に下線・文字色と背景色の反転などもできる。30番台は文字色、40番台は背景色。

ターミナルのタイトル

\e]0;...\a はターミナルのタイトルに文字列を表示させる。デフォルト設定の場合は \u@\h: \w の変換結果が表示される。

.bashrc では PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" となっているが、全体をダブルクォートで囲っているため変数がその場で展開され、debian_chroot を後からタイトルに反映させることはできなくなっている。

試してみる

これらの機能はプロンプトに限らず、ターミナルに出力するだけで効果がある。簡単な試し方として、echo コマンドなら -e オプションでバックスラッシュ文字列を変換してくれる。

user@host:~$ PS1='\u@\h:\w\$ '         # プロンプトから設定を消しておく
user@host:~$ echo -e '\e[32mfoobar'    # 緑字に変更
foobar
user@host:~$ echo -e '\e]0;foobar\a'   # タイトル変更

user@host:~$ . ~/.bashrc               # 設定を再読み込みすれば大抵は元通り
user@host:~$ echo -ne '\e[0m'          # 色が消えなければ手動で消す
user@host:~$ exit                      # どうしても直らなければ一旦ターミナルを閉じる

目的別まとめ

  • プロンプトらしい文字列表示だけなら PS1='\u@\h:\w\$ ' みたいに短く済む
  • 変数の内容を表示させたければ ${変数名} などを埋め込む。echo $PS1 としたときに未展開のまま表示され、\$ ともなっていなければOK
    • ${変数名:+代替文字列}${変数名:-デフォルト文字列} などを使えばより凝った設定ができる
    • ちなみに変数展開だけでなく、コマンド置換 $(コマンド) や算術展開 $((式)) も使える
  • 文字を装飾したければ \[\e[...m\] を間に入れる。適宜 \[\e[0m\] などして設定をリセットすること
  • ターミナルのタイトルを変更したければ \[\e]0;...\a\] を加える

参考


  1. これを使わずに着色設定をしたことがあるが、コマンドを履歴から出したときなどに表示がおかしくなった 

39
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
36