rcmdnk's blog

20130501_bashrc_200_200

Macでは普段iTerm2を使っているのですが、 ふと、もともと入ってるターミナル.appを立ち上げた所、 PROMPT_COMMANDがおかしくてエラーがでたので修正しました。

.bashrcでのPROMPT_COMMANDの設定

自分用の.bashrc内で、いくつか

PROMPT_COMMAND="${PROMPT_COMMAND:+${PROMPT_COMMAND};}command"

という形で新しいcommandPROMPT_COMMANDに追加しています 1

これは、PROMPT_COMMANDに何らかのコマンドがあれば、最後に;を加えて 新しいコマンドを付け加える、というつもりで、 前提としてPROMPT_COMMANDの最後に;がついてないということがありました。

ターミナル.app上でのPROMPT_COMMAND

Macのターミナル.appには新しいウィンドウやタブを開くとき、 現在作業中の所と同じディレクトリで開く事が出来るオプションがあります。

このディレクトリの定義はエスケープシーケンスを使って保存していて、 /etc/.bashrcを見ると

/etc/bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
   return
fi

PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize
# Tell the terminal about the working directory at each prompt.
if [ "$TERM_PROGRAM" == "Apple_Terminal" ] && [ -z "$INSIDE_EMACS" ]; then
    update_terminal_cwd() {
        # Identify the directory using a "file:" scheme URL,
        # including the host name to disambiguate local vs.
        # remote connections. Percent-escape spaces.
    local SEARCH=' '
    local REPLACE='%20'
    local PWD_URL="file://$HOSTNAME${PWD//$SEARCH/$REPLACE}"
    printf '\e]7;%s\a' "$PWD_URL"
    }
    PROMPT_COMMAND="update_terminal_cwd; $PROMPT_COMMAND"
fi

と言った様になっていて、update_terminal_cwdと言う関数内で \e]7;~\aにディレクトリ情報を送り、この情報をターミナル.appは使っている様です。 この関数をPROMPT_COMMANDで呼んでいます。

従って、上のターミナル.appの環境設定の一番下にもある注意の様に、もし.bashrc 等でPROMPT_COMMANDを上書きしてこの設定を消してしまえば この環境設定で同じ作業ディレクトリを選んでも機能しなくなります。

この設定はTERM_PROGRAMApple_Terminal(ターミナル.app) の場合(かつemacs内でのshellで無い場合) のみに加わるのでiTerm等、他のターミナルアプリでは /etc/bashrcPS1を設定するのみになります。

問題点

問題なのは

PROMPT_COMMAND="update_terminal_cwd; $PROMPT_COMMAND"

となっている部分で、この時点でPROMPT_COMMANDが定義されていないと、 結果的に

PROMPT_COMMAND="update_terminal_cwd;"

と言う様に最後が;で終わる形になってしまいます。

このまま上のある様に;をさらに付け加えてしまうと

-bash: syntax error near unexpected token `;'

の様なエラーが毎回コマンド打つ事に出て来るようになってしまいます。

普段使ってるLinux(Redhat系)では/etc/bashrc内で

PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'

と言った様に最後が;で無い形で終わっているので 両者で動かすためにちょっと修正が必要です。

.bashrcの修正

.bashrcの先頭の方で次の様にしました。

.bashrc
1
2
3
4
5
6
7
8
9
10
11
...
# In Mac, it is already read.
if [[ ! "$OSTYPE" =~ "darwin" ]];then
  if [ -r /etc/bashrc ];then
    source /etc/bashrc
  fi
fi
# Remove the last ";" from PROMPT_COMMAND
PROMPT_COMMAND=`echo ${PROMPT_COMMAND}|sed 's/;$//'`
...
# }}}

/etc/bashrcを読み込んだ後にPROMPT_COMMANDの最後の;を取り除いています。

また、.bashrcの最初で/etc/bashrcを読み込むのですが、 Macの場合、新しいシェルの立ち上げ時に自動的に/etc/bashrcが 読み込まれる様で、上にあるupdate_terminal_cwdが2重に 記述されていたので、 Macの場合("$OSTYPE" =~ "darwin")では.bashrc内からは 読み込まない様にもしました。

あまりこの辺の情報を探しても見つからなかったのですし、 Macのターミナルの使い方的な話でも普通に/etc/bashrcを 呼ぶ様な.bashrcを紹介しているようなページしか 見当たらなかったのですが、あまり気になる所ではないですかね… (ま、今回まで自分も気付かなかったわけだし…)

その他

と、今回気付いた点のもう一つが、普段使っているLinuxの方では上にあるように PROMPT_COMMANDで ウィンドウのタイトル、アイコン名(\033]0;~\007)を変更するように /etc/bashrc内で設定している事です。

そういえばそうだった、という感じで、昔見た覚えがありますが、 最近これをPS1の変数内で行なっているので、2重に行なっていることになります。

PS1の方が後に実行されるので問題は無いのですが、ちょっと気持ち悪い。 ただ、PROMPT_COMMANDにしても、後に付け加えれば2重になるので、 以前、その様に設定してた時も同じと言えば同じです。

基本的にはどこでも事前に設定されているコマンドが必要な事は 殆ど無いので、いっその事.bashrc内で1回リセットしてしまっても 良いのかもしれませんが、 今回のターミナルの様に特殊に使ってる場合もあるということが分かったので、 差し当たりそのままにしておきます。

Sponsored Links
  1. ${A:+B}でAが定義されてない、またはNULL(空)の場合にはNULLを返し、 NULL以外の何らかの値が入っていればBを返します。

Sponsored Links

« 英文法チェックソフト: Ginger Octopressへ絵文字の導入 »

}