ディレクトリツリー/ファイル名を使用する場合のコンパクトbashプロンプト


16

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短いプロンプトを取得して、特定の文字数を超えないように、ディレクトリ名を「ラップ」および「コンパクト」にする変数を定義する方法はありますか?


1
幸いなことに、シェルプロンプトをカスタマイズする方法を読んだ場所を覚えています:tldp.org/HOWTO/Bash-Prompt-HOWTO/x783.html Bash Prompt HOWTOの著者であり、それに貢献してくれたGiles Orrに感謝します。
16

unix.stackexchange.com/a/216871/117549(kshベースですが、同様のアイデア)も参照してください
ジェフシャラー

回答:


16

まず、単に\wwith を変更したい場合があります\W。これにより、現在のディレクトリの名前のみが出力され、パス全体は出力されません。

terdon@oregano:/home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name $ PS1="\u@\h:\W \$ "
terdon@oregano:my_actual_directory_with_another_long_name $ 

ディレクトリ名自体が長すぎる場合、それでも十分ではないかもしれません。その場合、PROMPT_COMMANDこの変数を使用できます。これは、各プロンプトが表示される前にコマンドとして値が実行される特別なbash変数です。したがって、現在のディレクトリのパスの長さに基づいて目的のプロンプトを設定する関数に設定すると、目的の効果を得ることができます。たとえば、次の行をに追加します~/.bashrc

get_PS1(){
        limit=${1:-20}
        if [[ "${#PWD}" -gt "$limit" ]]; then
                ## Take the first 5 characters of the path
                left="${PWD:0:5}"
                ## ${#PWD} is the length of $PWD. Get the last $limit
                ##  characters of $PWD.
                right="${PWD:$((${#PWD}-$limit)):${#PWD}}"
                PS1="\[\033[01;33m\]\u@\h\[\033[01;34m\] ${left}...${right} \$\[\033[00m\] "
        else
                PS1="\[\033[01;33m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] "
        fi


}
PROMPT_COMMAND=get_PS1

効果は次のようになります。

terdon@oregano ~ $ cd /home/mydirectory1/second_directory_with_a_too_long_name/my_actual_directory_with_another_long_name
terdon@oregano /home...th_another_long_name $ 

10

キャラクターリターンを追加することがこれに対する私の主な解決策です

したがって、私のプロンプト(他のものもあり、さらに長くなります)は次のようになります。

ここに画像の説明を入力してください

$が新しい行として返されていることに気付くでしょう。

私はこれを達成します

HOST='\[\033[02;36m\]\h'; HOST=' '$HOST
TIME='\[\033[01;31m\]\t \[\033[01;32m\]'
LOCATION=' \[\033[01;34m\]`pwd | sed "s#\(/[^/]\{1,\}/[^/]\{1,\}/[^/]\{1,\}/\).*\(/[^/]\{1,\}/[^/]\{1,\}\)/\{0,1\}#\1_\2#g"`'
PS1=$TIME$USER$HOST$LOCATION'\n\$ '

別の行であっても、次のような非常に長いディレクトリツリー

/home/durrantm/Dropbox/96_2013_archive/work/code/ruby__rails に短縮されます

/home/durrantm/Dropbox/_/code/ruby__rails

すなわち、「トップ3ディレクトリ/ _ /ボトム2ディレクトリ」は通常私が気にすることです

これにより、ディレクトリツリーの長さが原因で行が長くなりすぎることがなくなります。常に完全なディレクトリツリーが必要な場合は、LOCATIONを調整するだけです。

LOCATION=' \[\033[01;34m\]`pwd`'


1
あなたのプロンプトは実際にどこに含まれてい$ ますか?(これを参照してください。)
G-Manは「Reinstate Monica」と言います

最後に\ $を追加しました、ありがとう。通常、私はまた私のgitのブランチを示しているので、それはだったが、それはここのためにあまりにも多くの詳細である
マイケル・デュラント

1
何?改行なし?SGR0がありませんか?
G-Manが「Reinstate Monica」と言う

改行を追加
マイケルデュラント

3

〜/ .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$

1

長いパスを短縮する解決策ではありませんが、すべてのパス情報を表示したまま概要を把握する便利な方法は、最後の文字の前に改行を追加することです。この方法では、カーソルが常に同じ列で開始されます。パスが長すぎて折り返されても、コンソールウィンドウは前の行をあまり速くスクロールしないように十分高くなければなりません。より明確にするために、色コードを削除しました。

murphy@seasonsend:~
$ echo $PS1
\u@\h:\w\n\$
murphy@seasonsend:~
$ 

1

私はこれを使用し、複数の行に折り返し、長さ分インデントする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のタイトルバーのパスは折り返されておらず、省略されていません。これは、上記の関数に他の回答のいずれかを組み込むことで実行できます。)


0

別の方法として、私の.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はこちらです。

これはコンテキストを保持し、zshで同じ形式のディレクトリをすばやくタブ補完できるため、非常に便利です。(たとえば、タイピングcd /h/m/s/<tab>はに自動補完されますcd /home/mydirectory1/second_directory


これは、PS1プロンプトの定義方法に関するOPの質問にどのように適用されますか?
アントン

明確にするために編集され、$ tはPS1になります
リチャード

0

このPythonスクリプトを使用しみてください。質問で希望したとおりに、パス名の個々のセクションを切り取ります。また、3列ではなく1列のみを使用するUnicode省略記号も使用します。

パスの出力例(30文字の制限を指定した場合):

/home/mydir…/second…/my_actua

このソリューションは、を使用してディレクトリ名のUnicodeを正しく処理することに注意してくださいwcswidth${#PWD}、他の回答で使用されているように、UTF-8文字が含まれるパスの視覚的な幅を誤って判断します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.