シェルスクリプト内で現在のターミナルタブのタイトルを変更する

シェルスクリプト内で現在のターミナルタブのタイトルを変更する

現在のターミナルタブのタイトルを変更するスクリプトを見つけました:

#!/usr/bin/env bash
T=$1
ORIG=$PS1
TITLE="\e]2;$T\a"
PS1=${ORIG}${TITLE}
echo "Terminal tab title changed to $T"

ターミナルに直接入力するとうまく機能します(例TITLE="\e]2;HELLO\a"

しかし、シェル スクリプト (rename.sh) 内では $PS1 が空であり、スクリプトは機能しません。

rename.sh HELLO は出力されます"Terminal tab title changed to HELLO" が、ターミナルのタイトルは変更されません。スクリプト内の $PS1 は空です。

誰かこれを理解するのを手伝ってくれませんか?

答え1

このスクリプトは、シェルの対話型プロンプトを、ウィンドウ タイトルを操作するための制御コードを含む文字列に設定することによって機能しますxterm。シェルのプロンプトが表示されるたびに、ウィンドウ タイトルを変更するための制御コードが出力されます。

しかし、もちろん、スクリプト内では対話型プロンプトは表示されないため、これらのコマンドは目に見える効果はありません (ただし、スクリプト内から別の対話型シェルを起動すると、ウィンドウ タイトルの変更を確認できます)。また、スクリプトは親プロセスの環境を変更できないため、スクリプトが終了すると変更は失われます。

とにかく、スクリプトから、制御コードを直接印刷することもできます。

printf '\033]2;Hello\a'

これにより、ウィンドウのタイトルが一度変更されますが、後で他のプログラムが再度タイトルを変更すると、古いタイトルは失われます。プロンプトを変更するトリックは広く普及しています。これは、過去に人気のあったプログラムの中には、好みに合わせてウィンドウのタイトルを変更した直後に、そのタイトルを変更するものが多かったためです (ただし、これはもはや一般的な問題ではないと思います)。欠点は、ウィンドウのタイトルを変更する正当な理由がある場合、シェルがプロンプトを再度表示するとすぐに、そのタイトルが置き換えられてしまうことです。

現在のシェルのプロンプトを変更するコードが必要な場合、通常のスクリプトにそれらを入れることはできませんが、sourceスクリプト ファイルを使用するか、代わりにシェル関数にコマンドを入れることができます (通常、永続化するために Bash プロファイルで行われます)。

ちなみに、Bash プロンプトには、プロンプトの表示幅を計算する際に、プロンプトの一部が実質的にゼロ幅であることを Bash に伝えるための追加の制御コードが含まれている必要があります。たとえば、長いコマンドを入力してからバックスペースが必要な場合、行の折り返しが不規則になることがわかります。Bash はプロンプトを再描画しようとしますが、画面制御コードがプロンプトの幅に関係していると判断して、間違った場所で再描画します。これらのコード\[と、\]その周囲に Bash 制御コードを追加する必要があります。

PS1="$ORIG\[$TITLE\]"

(中括弧は実際には何の役にも立たず、読みにくくなるため、削除しました。)

答え2

この変数はPS1対話型シェルでのみ使用されるため、アクセスするにはスクリプトを で開始する必要がありますbash -i rename.sh

最小限の例:

$ echo 'echo $PS1' > test

比較する

$ bash test
$ bash -i test

スクリプトを実行可能ファイルとして直接実行するには、最初の行に次のコードを追加します。

#!/bin/bash -i

知らせこれは、 chmod を実行してスクリプトを直接実行した場合にのみ機能します (例: ./rename.sh)。 では機能しません。bash rename.shそれ以外の場合は、 を再度呼び出す必要がありますbash -i rename.sh

編集

ターミナルタイトルを直接変更するには、制御コードを直接エコーします。

echo -e '\033]2;SomeTitle\007'

またはスクリプト内で変数を使って

title="SomeTitle"
echo -e '\033]2;'$title'\007'

関連情報