Ubuntu 14.04とbash
のシステムでは、次の内容で終わるPS1
変数があります。
\u@\h:\w\$
プロンプトが次のように表示されるようにします
user@machinename:/home/mydirectory$
ただし、現在のディレクトリが長い名前である場合や、現在のディレクトリが長い名前のディレクトリ内にある場合があるため、プロンプトは次のようになります。
user@machinename:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name$
これはターミナルの行を埋め、カーソルは別の行に移動します。これは面倒です。
代わりに次のようなものを入手したい
user@machinename:/home/mydirectory1/...another_long_name$
PS1
変数を定義して、特定の文字数を超えないようにディレクトリ名を「ラップ」および「圧縮」して、より短いプロンプトを取得する方法はありますか?
作成された〜/ .bash_Prompt:
maxlen=36
# set leftlen to zero for printing just the right part of the path
leftlen=19
shortened="..."
# Default PWD
nPWD=${PWD}
if [ ${#nPWD} -gt $maxlen ]; then
offset=$(( ${#nPWD} - $maxlen + $leftlen ))
nPWD="${nPWD:0:$leftlen}${shortened}${nPWD:$offset:$maxlen}"
else
nPWD='\w'
fi
echo "\u@\h:$nPWD\$ "
〜/ .bash_profileに追加:
function Prompt_command {
export PS1=$(~/.bash_Prompt)
}
export Prompt_COMMAND=Prompt_command
出力は次のとおりです。
user@machinename:/home/mydirectory1/...another_long_name$
私はこれを使用し、複数行に折り返してuser@Host
の長さだけインデントするため、現在のPS1
は事実上 '\u@\h:\w$
'であると想定しています。パスは切り捨てられず、現在の端子幅に適応します。 /
でパスを分割するだけなので、本当に長いディレクトリをエレガントに処理しません(ただし、選択/コピーのためのスペースは保持します)。これにより、常に少なくとも20文字のスペースが入力可能になります。
readonly _PS1="${PS1}" 2>/dev/null
function myprompt()
{
local IFS
local nn nb pbits xpwd="" ww=60 len=0 pp='\\w\$ '
local indent uh="${LOGNAME}@${HOSTNAME//.*/}"
test -n "$COLUMNS" && let ww=$COLUMNS-20 # may be unset at startup
PS1="${_PS1}"
if [ ${#PWD} -ge $ww ]; then
printf -v indent "%${#uh}s%s" " " "> " # indent strlen(user@Host)
IFS=/ pbits=( $PWD ); unset IFS
nb=${#pbits[*]}
for ((nn=1; nn<nb; nn++)) {
if [ $(( $len + 1 + ${#pbits[$nn]} )) -gt $ww ]; then
xpwd="${xpwd}/...\n${indent}..."
len=0
fi
xpwd="${xpwd}/${pbits[$nn]}"
let len=len+1+${#pbits[$nn]}
}
# add another newline+indent if the input space is too tight
if (( ( ${#uh} + len ) > ww )); then
printf -v xpwd "${xpwd}\n%${#uh}s" " "
fi
PS1="${PS1/$pp/$xpwd}$ "
fi
}
Prompt_COMMAND=myprompt
これは、\w
からマジック\w$
(この場合はPS1
のみに一致)を取得して$PWD
に置き換え、プレーンな文字列としてラップすることで機能します。 PS1
に保存されている元の値から_PS1
を毎回再計算します。これは、「不可視」のエスケープも保持されることを意味します。xterm
の元の完全なプロンプト文字列と太字のプロンプト:
PS1="\[\033]0;\u@\h:\w\007\]\[$(tput bold)\]\u@\h\[$(tput sgr0)\]:\w$ "
そして、最終的な結果は80列のターミナルになります。
mr@onomatopoeia:~$ cd /usr/src/linux/tools/perf/scripts/Perl/Perf-Trace-Util/lib/Perf/Trace
mr@onomatopoeia:/usr/src/linux/tools/perf/scripts/Perl/Perf-Trace-Util/lib/...
> .../Perf/Trace$ _
printf -v var
が使用されるため、これはbash-3.2から機能します。 さまざまな複雑さ のため、PS1
の他のバリエーションには調整が必要です。
(xtermタイトルバーのパスは折り返されたり省略されたりしません。これは、他の回答の1つを上記の関数に組み込むことで実行できます。 )
this Python script を使用してみてください。これは、質問で希望したとおりに、パス名の個々のセクションを切り取ります。また、Unicodeの省略記号を使用して、 3列ではなく1列のみ。
パスの出力例(30文字の制限が指定されている場合):
/home/mydir…/second…/my_actua…
このソリューションは wcswidth
を使用してディレクトリ名のUnicodeを正しく処理することに注意してください。 ${#PWD}
は他の回答で使用されていますが、UTF-8文字を含むパスの視覚的な幅を誤って判断します。
別の方法として、私の.zshrcでは、ピクセル幅が特定の幅を超えている場合は、各ディレクトリの最初の文字に省略します。
user@machinename:/home/mydirectory1/second_directory
user@machinename:/home/mydirectory1/second_directory/my_actual_directory
になる:
user@machinename:/h/mydirectory1/second_directory
user@machinename:/h/m/s/my_actual_directory
これを行うzsh関数は次のとおりです。
# get the path
t=`print -P "%m:%~"`;
t=`echo $t | sed -r 's/([^:])[^:]*([0-9][0-9]):|([^:])[^:]*([^:]):/\1\2\3\4:/'`;
oldlen=-1;
# create 4 buckets of letters by their widths
t1="${t//[^ijlIFT]}";
t2="${t//[ijlIFTGoQMmWABEKPSVXYCDHNRUw]}";
t3="${t//[^ABEKPSVXYCDHNRUw]}";
t4="${t//[^GoQMmW]}";
# keep abbreviating parent directories in the path until under 456 pixels
while (( ( ( ${#t1} * 150 ) + ( ${#t2} * 178 ) + ( ${#t3} * 190 ) + ( ${#t4} * 201 ) ) > 4560 && ${#t}!=oldlen)) {
oldlen=${#t};
t=`echo $t | sed 's/\/\(.\)[^\/][^\/]*\//\/\1\//'`;
t1="${t//[^ijlIFT]}";
t2="${t//[ijlIFTGoQMmWABEKPSVXYCDHNRUw]}";
t3="${t//[^ABEKPSVXYCDHNRUw]}";
t4="${t//[^GoQMmW]}";
};
PS1=$t
これを実際に使用してターミナルのタイトルを更新し、複数のタブがある場合、どのタブがどのタブであるかをまっすぐに保つことができます。これを行う完全な.zshrcは here です。
これはコンテキストを保持し、zshでは同じ形式のディレクトリをすばやくタブで補完できるため、非常に便利です。 (たとえば、cd /h/m/s/<tab>
と入力すると、cd /home/mydirectory1/second_directory
にオートコンプリートされます)