FreeBSD shで現在のディレクトリを端末タイトルに表示する
複数の端末を同時に開いて作業していると、それぞれの作業ディレクトリを タイトルバーだけで判別できると便利です。
たとえば、現在のディレクトリが次のパスである場合、
/home/hodong/projects/nimfsoft.com
端末タイトルを次のように表示できます。
~/projects/nimfsoft.com
現在のディレクトリがホームディレクトリの外にある場合は、フルパスを 表示します。
/usr/local/src
この記事では FreeBSD の /bin/sh と ~/.shrc を使用します。
端末タイトルを変更する仕組み
xterm 互換の端末エミュレーターでは、OSC(Operating System Command) エスケープシーケンスを使ってタイトルを変更できます。
printf '\033]0;%s\007' '新しい端末タイトル'
各部分の意味は次のとおりです。
\033 ESC 文字
]0; アイコン名とウィンドウタイトルを設定
%s 表示する文字列
\007 BEL で OSC シーケンスを終了
したがって、現在のディレクトリをそのまま指定できます。
printf '\033]0;%s\007' "$PWD"
実際に利用できるかどうかは、端末エミュレーターとその設定に依存します。
ホームディレクトリを ~ に短縮する
$PWD が $HOME と同じ、またはその配下にある場合は、ホーム
ディレクトリ部分を ~ に置き換えます。
set_terminal_title() {
if [ -n "${HOME-}" ]; then
case "$PWD" in
"$HOME")
_terminal_title_path='~'
;;
"$HOME"/*)
_terminal_title_path="~${PWD#"$HOME"}"
;;
*)
_terminal_title_path=$PWD
;;
esac
else
_terminal_title_path=$PWD
fi
printf '\033]0;%s\007' "$_terminal_title_path"
unset _terminal_title_path
}
${HOME-} は、HOME が未設定の場合に空文字列へ展開されます。これにより
未設定値を有効なホームディレクトリとして扱うことを防ぎます。
ホームディレクトリが正しく設定されている場合は、case 文で現在の
パスを分類します。
case "$PWD" in
"$HOME")
_terminal_title_path='~'
;;
"$HOME"/*)
_terminal_title_path="~${PWD#"$HOME"}"
;;
*)
_terminal_title_path=$PWD
;;
esac
現在のディレクトリがホームディレクトリと完全に同じ場合、タイトルは
~ になります。
/home/hodong -> ~
現在のディレクトリがホームディレクトリの配下にある場合は、$HOME
部分を削除し、残ったパスの先頭に ~ を付けます。
/home/hodong/projects/nimfsoft.com
-> ~/projects/nimfsoft.com
${PWD#"$HOME"} は、$PWD の先頭から $HOME に一致する最短の部分を
削除します。
たとえば、次の環境では、
HOME=/home/hodong
PWD=/home/hodong/projects/nimfsoft.com
の場合、結果は次のようになります。
/projects/nimfsoft.com
先頭に ~ を追加すると、最終的なタイトルは次のようになります。
~/projects/nimfsoft.com
になります。
"$HOME"/* を独立したパターンとして使うため、
/home/hodong2/projects を誤って /home/hodong の配下と判断することは
ありません。
/home/hodong2/projects
-> /home/hodong2/projects
_terminal_title_path は一時的なシェル変数です。シェル関数内の変数は
通常、現在のシェルに残るため、使用後に unset して名前の衝突を避けます。
cd の実行後にタイトルを更新する
シェル起動時に一度だけタイトルを設定しても、ディレクトリを移動した後は 古い表示のままです。
次の関数は元のシェル組み込み cd を呼び出し、移動に成功した場合だけ
タイトルを更新します。
cd() {
command cd "$@" || return $?
set_terminal_title
}
関数内で直接 cd "$@" を実行すると、同じ関数を再び呼び出して再帰に
なります。
cd "$@"
command cd "$@" を使うと、同名の関数を迂回し、シェル組み込みの
cd を実行します。
command cd "$@"
"$@" は渡された引数をそのまま保持します。
cd
cd -
cd /usr/local/src
移動に失敗した場合は失敗ステータスを返し、タイトルは変更しません。
command cd "$@" || return $?
したがって、存在しないディレクトリへ移動しようとしても、現在の ディレクトリと端末タイトルはそのまま維持されます。
最終的な .shrc パッチ
次のパッチを ~/.shrc に適用します。
--- a/.shrc 2026-07-15 19:28:53.358286000 +0900
+++ b/.shrc 2026-07-15 19:47:56.461994000 +0900
@@ -46,6 +46,37 @@
bind ^[[5~ ed-move-to-beg
bind ^[[6~ ed-move-to-end
+# Update terminal title to the current working directory.
+set_terminal_title() {
+ if [ -n "${HOME-}" ]; then
+ case "$PWD" in
+ "$HOME")
+ _terminal_title_path='~'
+ ;;
+ "$HOME"/*)
+ _terminal_title_path="~${PWD#"$HOME"}"
+ ;;
+ *)
+ _terminal_title_path=$PWD
+ ;;
+ esac
+ else
+ _terminal_title_path=$PWD
+ fi
+
+ printf '\033]0;%s\007' "$_terminal_title_path"
+ unset _terminal_title_path
+}
+
+# Change directory and update the terminal title.
+cd() {
+ command cd "$@" || return $?
+ set_terminal_title
+}
+
+# Set the initial terminal title.
+set_terminal_title
+
# set prompt: ``username@hostname:directory $ ''
PS1="\u@\h:\w \\$ "
最初に set_terminal_title を呼び出すことで、.shrc を読み込んだ時点の
作業ディレクトリをタイトルへ反映します。
set_terminal_title
その後は cd が成功するたびにタイトルが更新されます。
設定を再読み込みします。
. ~/.shrc
プロジェクトディレクトリへ移動すると、
cd ~/projects/nimfsoft.com
タイトルは次のようになります。
~/projects/nimfsoft.com
ホームディレクトリの外ではフルパスを表示します。
cd /usr/local/src
/usr/local/src
PS1 内で関数を呼び出さない理由
次のように書く方法も考えられます。
PS1='$(set_terminal_title)\u@\h:\w \$ '
しかし、この記事で使用した FreeBSD sh 環境では意図どおりに動作せず、
プロンプト表示が崩れ、タイトルも更新されませんでした。
そのため、既存のプロンプトは変更しません。
PS1="\u@\h:\w \\$ "
プロンプトの再評価動作には依存せず、cd が成功した直後にタイトルを
更新します。
注意事項
この設定を利用するには、端末エミュレーターが OSC タイトルシーケンスを サポートし、アプリケーションによるタイトル変更を許可している必要が あります。
この記事では一般的なディレクトリ名を想定しています。ディレクトリ名に ESC や BEL などの制御文字が含まれる可能性がある場合は、OSC シーケンスへ 埋め込む前にパスを無害化する必要があります。
タイトルは、ここで定義した cd 関数を通じてディレクトリを変更したときに
更新されます。シェル開始時のタイトルは明示的な最初の呼び出しで設定します。
まとめ
最終的な表示規則は次のとおりです。
/home/hodong -> ~
/home/hodong/projects -> ~/projects
/home/hodong/projects/nimfsoft.com -> ~/projects/nimfsoft.com
/home/hodong2/projects -> /home/hodong2/projects
/usr/local/src -> /usr/local/src
小さな設定ですが、複数のプロジェクトを同時に扱うときに端末を区別しやすく なります。